Caché数据库Ado.Net纠葛之面向接口编程

什么是Ado.NET
ADO.NET是一种数据访问技术,使得应用程序可以连接到数据存储,并以各种方式操作存储在其中的数据。
该技术基于.NET Framework,与.NET Framework类库的其余部分高度集成。ADO.NET API的设计,使得可以从所有面向.NET Framework的语言中使用该API,如Visual Basic、C#、J#、和Visual C++。ADO.NET软件栈包含两个主要部分:提供者和服务。
ADO.NET的“提供者”是一些组件,这些组件知道如何与特定的数据存储设施交互(例如,有一个提供者与SQL Server交互,另一个提供者与Oracle数据库交互)。所有的提供者都向外提供一个统一的API接口,ADO.NET软件栈中的其他层在此API之上建立。
ADO.NET还包括基于提供者而建立的一些服务,设计这些服务的目的,是为了方便编写应用程序。其中一个服务是内存中的缓存(in-memory cache),缓存保存了数据的关系形式,并执行修改跟踪和约束验证等功能;该服务通过ADO.NET DataSet接口提供,包括一些与提供者层进行交互的组件。
五大对象分别是:
1、Connection(连接数据库)
2、Command(执行T-SQL语句)
3、DataAdapter(用户填充DataSet,断开模式)
4、DataReader(读取数据库,一种只读模式,只向前的)
5、DataSet(数据集,好比电脑的内存)
什么是Caché的Ado.Net
Caché的Ado访问层作为Caché提供给.Net的组件允许我们用统一的Ado操作Caché数据库。在Caché2010和2016表现为“InterSystems.Data.CacheClient.dll”,在IRIS表现为“InterSystems.Data.IRISClient.dll”。.Net程序通过引用该组件使用提供的Connection、Command、DataAdapter、DataReader等操作数据库进行增删改查操作。
Caché的Ado.Net的问题
由于Caché的主要提供语言是M语言,虽然声称支持SQL标准,实际对SQL标准支持的还是比较基本的。在使用过程中碰到由2010库到2016库出现的DataReader在有的类表的查询读取最后一行数据报异常的问题(只能用如下方式解决)。

				try
                {
     
                    //遍历读取数据
                    while (sdr.Read())
                    {
     
                        //行数加1
                        rowCount++;
                        //只取起始范围的数据
                        if (findAll || ((rowCount > rowFrom) && (rowCount <= rowTo)))
                        {
     
                            if (firstFlag)
                            {
     
                                retLength = sb.Length;
                                JsonHelper.MakeObjJsonByPropertyArr(sb, properties, sdr, fields);
                                //置第一条标识为假
                                firstFlag = false;
                            }
                            else
                            {
     
                                retLength = sb.Length;
                                sb.Append(",");
                                JsonHelper.MakeObjJsonByPropertyArr(sb, properties, sdr, fields);
                            }
                        }
                    }
                    //行数
                    if (adoHelper.RowCount != "")
                    {
     
                        rowCount = Convert.ToInt32(adoHelper.RowCount);
                        adoHelper.RowCount = "";
                    }
                }
                catch (Exception ex)
                {
     
                    sb.Remove(retLength, sb.Length - retLength);
                    LIS.Core.Util.LogUtils.WriteExceptionLog("读取数据出现内部已知的异常", ex);
                }

还有存储过程返回值莫名多不可见字符的问题(只能特殊处理)。

			case DatabaseType.CACHE:
                    retValue = ((IDbDataParameter)(cmd.Parameters[cmd.Parameters.Count - 1])).Value.ToString();
                    retValue = retValue.Split((char)1)[0];
                    retValue = retValue.Split((char)13)[0];
                    break;

还有连接时间久了释放时物理TCP都已经断开的连接还在连接池一直取处于错误的连接和调用的M切换命名空间没切回来Connection对象一直是切换后的控制导致M调不到的问题(只能清理连接池)。

			catch (Exception e)
            {
     
                if (cmdType == CommandType.StoredProcedure)
                {
     
                    //异常就清除连接池
                    DbFactory.ClearPool(conn);
                }
                //赋值错误信息
                errorInfo = e.Message;
                //写入日志
                LogUtils.WriteSqlLog(cmdText + ":" + e.Message + ",失败!");
                return 0;
            }
			/// 
        /// 清除指定连接
        /// 
        /// 
        public void ClearPool(IDbConnection conn)
        {
     
            if (conn != null)
            {
     
                try
                {
     
                    CacheConnection.ClearPool(conn as CacheConnection);
                }
                catch
                {
     
                }
            }
        }

正常我们只要实现下面个接口就可以确保基于Ado的ORM访问层正常

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using InterSystems.Data.CacheClient;

namespace LIS.DAL.Base
{
     
    /// 
    /// [功能描述: cache数据库的基础接口实现]

/// [创建者: zlz]

/// [创建时间: 2015-03-15]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class CacheBase : LIS.DAL.ORM.DBUtility.IDbFactory { /// /// 存当前连接串 /// public static string CurConnString = ""; /// /// 构造函数 /// public CacheBase() { //没强制指定连接串 if (ConnectionString == null || ConnectionString == "") { StrDbType = System.Configuration.ConfigurationSettings.AppSettings["DBType"]; ConnectionString = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString_Detail"]; if (ConnectionString == "") { //不频繁解密,浪费性能 if (CurConnString == "") { ConnectionString = LIS.DAL.Base.Util.DesUtil.DecryptDES(System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"]); CurConnString = ConnectionString; } else { ConnectionString = CurConnString; } } string ip = System.Configuration.ConfigurationSettings.AppSettings["ServiceIP"]; ConnectionString = ConnectionString.Replace("#", ip); } } /// /// 数据库类型 /// public string StrDbType { get; set; } /// /// 连接串 /// public string ConnectionString { get; set; } /// /// 返回数据库占位符 /// /// 数据库占位符 public string CreateDbParmCharacter() { return "?"; } /// /// 返回数据库连接对象 /// /// 数据库连接对象 public IDbConnection CreateDbConnection() { CacheConnection connCache = new CacheConnection(ConnectionString); //测试连接,防止僵尸连接存在连接池中 //声明命令接口 IDbCommand cmd = new CacheCommand(); try { cmd.Connection = connCache; cmd.CommandText = "select * from dbo.SYS_ConnectionTest"; cmd.CommandType = CommandType.Text; connCache.Open(); cmd.ExecuteScalar(); } catch { //执行简单的测试sql测试连接的可用性 //测试连接可用性,用一个最简单的sql,不可以从连接池移除,创建新的连接 CacheConnection.ClearPool(connCache); connCache = new CacheConnection(ConnectionString); } finally { cmd.Dispose(); } //声明连接接口 IDbConnection conn = connCache; return conn; } /// /// 返回数据库命令对象 /// /// 数据库命令对象 public IDbCommand CreateDbCommand() { //声明命令接口 IDbCommand cmd = new CacheCommand(); return cmd; } /// /// 返回数据库适配器对象 /// /// 数据库适配器对象 public IDbDataAdapter CreateDataAdapter() { //声明数据适配器接口 IDbDataAdapter adapter = new CacheDataAdapter(); return adapter; } /// /// 返回数据库适配对象 /// /// 数据库命令对象 /// 数据库适配器对象 public IDbDataAdapter CreateDataAdapter(IDbCommand cmd) { //声明数据适配器接口 IDbDataAdapter adapter = new CacheDataAdapter((CacheCommand)cmd); return adapter; } /// /// 创建数据库参数 /// /// public IDbDataParameter CreateDbParameter() { //声明数据库参数接口 IDbDataParameter param = new CacheParameter(); return param; } /// /// 创建数据库参数数组 /// /// 大小 /// 参数数组 public IDbDataParameter[] CreateDbParameters(int size) { int i = 0; //声明数据库参数数组 IDbDataParameter[] param = null; param = new CacheParameter[size]; while (i < size) { param[i] = new CacheParameter(); i++; }; return param; } /// /// 创建数据库事务 /// /// 事务对象 public IDbTransaction CreateDbTransaction() { //根据连接串创建事务对象 IDbConnection conn = CreateDbConnection(); //如果连接是关闭的,打开连接 if (conn.State == ConnectionState.Closed) { conn.Open(); } //开始事务 return conn.BeginTransaction(); } /// /// 处理表名称 /// /// 表名称 /// 处理后的表名称 public string DealTableName(string tableName) { return tableName; } /// /// 处理属性名称 /// /// 属性名称 /// 处理后的属性名称 public string DealPropertyName(string propertyName) { return propertyName; } /// /// 清除指定连接 /// /// public void ClearPool(IDbConnection conn) { if (conn != null) { try { CacheConnection.ClearPool(conn as CacheConnection); } catch { } } } } }

然而到了IRIS数据库后连各个对象名称都不同了,还得新写引用新dll的和新类名的适配类(泪奔了)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using InterSystems.Data.IRISClient;

namespace LIS.DAL.Base
{
     
    /// 
    /// [功能描述: cache数据库的基础接口实现]

/// [创建者: zlz]

/// [创建时间: 2015-03-15]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class CacheBaseIRIS : LIS.DAL.ORM.DBUtility.IDbFactory { /// /// 存当前连接串 /// public static string CurConnString = ""; /// /// 构造函数 /// public CacheBaseIRIS() { //没强制指定连接串 if (ConnectionString == null || ConnectionString == "") { StrDbType = System.Configuration.ConfigurationSettings.AppSettings["DBType"]; ConnectionString = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString_Detail"]; if (ConnectionString == "") { //不频繁解密,浪费性能 if (CurConnString == "") { ConnectionString = LIS.DAL.Base.Util.DesUtil.DecryptDES(System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"]); CurConnString = ConnectionString; } else { ConnectionString = CurConnString; } } string ip = System.Configuration.ConfigurationSettings.AppSettings["ServiceIP"]; ConnectionString = ConnectionString.Replace("#", ip); } } /// /// 数据库类型 /// public string StrDbType { get; set; } /// /// 连接串 /// public string ConnectionString { get; set; } /// /// 返回数据库占位符 /// /// 数据库占位符 public string CreateDbParmCharacter() { return "?"; } /// /// 返回数据库连接对象 /// /// 数据库连接对象 public IDbConnection CreateDbConnection() { IRISConnection connCache = new IRISConnection(ConnectionString); //测试连接,防止僵尸连接存在连接池中 //声明命令接口 IDbCommand cmd = new IRISCommand(); try { cmd.Connection = connCache; cmd.CommandText = "select * from dbo.SYS_ConnectionTest"; cmd.CommandType = CommandType.Text; connCache.Open(); cmd.ExecuteScalar(); } catch { //执行简单的测试sql测试连接的可用性 //测试连接可用性,用一个最简单的sql,不可以从连接池移除,创建新的连接 IRISConnection.ClearPool(connCache); connCache = new IRISConnection(ConnectionString); } finally { cmd.Dispose(); } //声明连接接口 IDbConnection conn = connCache; return conn; } /// /// 返回数据库命令对象 /// /// 数据库命令对象 public IDbCommand CreateDbCommand() { //声明命令接口 IDbCommand cmd = new IRISCommand(); return cmd; } /// /// 返回数据库适配器对象 /// /// 数据库适配器对象 public IDbDataAdapter CreateDataAdapter() { //声明数据适配器接口 IDbDataAdapter adapter = new IRISDataAdapter(); return adapter; } /// /// 返回数据库适配对象 /// /// 数据库命令对象 /// 数据库适配器对象 public IDbDataAdapter CreateDataAdapter(IDbCommand cmd) { //声明数据适配器接口 IDbDataAdapter adapter = new IRISDataAdapter((IRISCommand)cmd); return adapter; } /// /// 创建数据库参数 /// /// public IDbDataParameter CreateDbParameter() { //声明数据库参数接口 IDbDataParameter param = new IRISParameter(); return param; } /// /// 创建数据库参数数组 /// /// 大小 /// 参数数组 public IDbDataParameter[] CreateDbParameters(int size) { int i = 0; //声明数据库参数数组 IDbDataParameter[] param = null; param = new IRISParameter[size]; while (i < size) { param[i] = new IRISParameter(); i++; }; return param; } /// /// 创建数据库事务 /// /// 事务对象 public IDbTransaction CreateDbTransaction() { //根据连接串创建事务对象 IDbConnection conn = CreateDbConnection(); //如果连接是关闭的,打开连接 if (conn.State == ConnectionState.Closed) { conn.Open(); } //开始事务 return conn.BeginTransaction(); } /// /// 处理表名称 /// /// 表名称 /// 处理后的表名称 public string DealTableName(string tableName) { return tableName; } /// /// 处理属性名称 /// /// 属性名称 /// 处理后的属性名称 public string DealPropertyName(string propertyName) { return propertyName; } /// /// 清除指定连接 /// /// public void ClearPool(IDbConnection conn) { if (conn != null) { try { IRISConnection.ClearPool(conn as IRISConnection); } catch { } } } } }

以上的种种都还不是要紧的,最要命的是这个Ado在没业务量的时候连小机和ECP没差异,在业务量上来之后连小机和ECP进行一个增删改查就是几毫米和上秒级的性能差异,果然还是对M支持最好,Ado机制不堪大用啊o(╥﹏╥)o。
困境探索
我们的程序已经在Ado的路上走得很远了,贸然换访问机制也不是一天两天的事。有什么方式可以不影响业务代码的情况切换访问机制。首先想到是否可以新包装ORM数据访问层,用调用M实现原来一样的接口?(但是ORM封装的功能也很多很深入,重新用M包装原来一样的接口效果工作量也很大,也很难包装的完全一致,所以不合实际)。后面想到从Ado.Net的接口层入手用M实现Ado几个类的接口,然后ORM调我们自己实现的Ado组件就可以确保ORM和上层的稳定性O(∩_∩)O哈哈~。有了思想就开干

首先包装M的执行SQL和存储过程M的方法。

/// w ##Class(LIS.WS.DHCLISService).GetSQLData("$StoredProcedure^LISSP.DHCRPVisitNumber_ReceiveVisitNumber","11$ZLPS$113C::1@$ZLPS$113^1^^12^1$ZLPS$",$c(0))
/// w ##Class(LIS.WS.DHCLISService).GetSQLData("INSERT INTO dbo.BTMI_MachineParameter(Active,DelimiterForSen,Serialnumber,DelimiterForAnt,RegisterDeviceDR,CommDirection,Sequence,LicenseKey,BaudRate,ViewQcMap,OpMessage,CName,RoomDR,Parity,PortNo,DelimiterForResults,WorkGroupMachineDR,IsChgTranEpis,DeviceCode,IFProgram,DelimiterForTests,IPAddress,JobID,StopBits,IsStart,StartWebService,ComPort,LName,HospitalDR,LinkWGMachines,Code,IsSendPanic,DataBits) VALUES('1','','','','','UI','1','','9600','','','微生物','','E','','\','16','0','1','',',','','','2','','','0','微生物','1','','MIC','0','7')",$c(0),$c(0))
/// w ##Class(LIS.WS.DHCLISService).GetSQLData("Select * from dbo.BT_Hospital")
/// w ##Class(LIS.WS.DHCLISService).GetSQLData("update dbo.BT_Hospital set CName='航空' where RowID=17")
/// w ##Class(LIS.WS.DHCLISService).GetSQLData("INSERT INTO dbo.SYS_TableLog(AddUserDR,AddDate,AddTime,ClientIPAddress,Remark,ActData,Action,RecordID,TableDR) values('113','20190929','41819','','','aaa','U','','213')")
ClassMethod GetSQLData(SQLText As %String(MAXLEN=32767), Param As %String(MAXLEN=32767), Session As %String(MAXLEN=1000)) As %GlobalCharacterStream [ WebMethod ]
{
     
	s SQLText=$g(SQLText),Session=$g(Session),Param=$g(Param)
	s ^TMP("exesql")=$lb(SQLText,Param,Session)
	Set $ZTrap = "ErrorHandle"
	s Xml=""
	s FuncRet=""
	s IsProcedure=0
	s RowCount=0
	s exeret=""
	//存储过程
	i SQLText["$StoredProcedure^" d
	.s IsProcedure=1
	.s ProcedureInfo=$p(SQLText,"^",2)
	.s ClassName=$p(ProcedureInfo,"_",1)
	.s FuncName=$p(ProcedureInfo,"_",2)
	.s FuncDoStr="(FuncRet) s FuncRet=$CLASSMETHOD("""_ClassName_""","""_FuncName_""""
	.f pi=1:1:$l(Param,"$ZLPS$") d
	..s CurPara=$p(Param,"$ZLPS$",pi)
	..s FuncDoStr=FuncDoStr_","""_CurPara_""""
	.s FuncDoStr=FuncDoStr_")"
 	.x (FuncDoStr,.FuncRet)
 	.s exeret="1"
 	//执行SQL
	e  d
	.Set rset = ##class(%ResultSet).%New()
	.Do rset.Prepare(SQLText)
	.s exeret=rset.Execute()
	.s PageSize=$p(Param,"^",1)
	.s PageIndex=$p(Param,"^",2)
	.s (SortName, SortType)=""
	.s Xml=##class(LIS.Util.DataSetXML).DataSetToSortStream(rset , SortName, SortType, PageSize, PageIndex, .RowCount)
	
	//返回结果
 	s objStream=##class(%GlobalCharacterStream).%New()
    d objStream.Write("")
    i (Xml'="")
    {
     
    	d objStream.CopyFrom(Xml)
    }
    s Err=""
    i IsProcedure=0 d
    .i exeret'="1" d
    ..s Err=##Class(LIS.WS.BLL.DHCDataJSON).DealForXML(exeret)
    ..s exeret=-1
    .//返回主键
    .e  d
    ..i $zcvt(SQLText,"U")["INSERT " d objStream.Write(""_rset.%RowID_"")
    e  d
    .d objStream.Write(""_FuncRet_"")
    d objStream.Write(""_exeret_""_Err_""_RowCount_"")
    d objStream.Write("")
	i IsProcedure=0 s ret=rset.Close()
 	q objStream
 	
ErrorHandle
    s err=$tr("执行SQL异常:"_$tr($ZERROR,"^","--")_".错误代码:"_$ECODE,"<>")
    s objStream=##Class(LIS.Util.Response).GetReturn("","-1",err)
    Quit objStream
}

然后就是实现C#方法调用上面的M方法

/// 
        /// 获得SQL数据XML
        /// 
        /// sql语句
        /// 参数
        /// 会话信息串
        /// 错误信息
        /// json串
        public static string GetCacheSQLDataXML(string SQLText, string Param, string session, out string errStr)
        {
     
            //如果传入的类名为空,直接抛出异常
            if (SQLText == string.Empty)
            {
     
                throw new LIS.Core.BaseException.BusinessException(LIS.Core.Const.ExcepitionCode.paraNullEx, LIS.Core.Const.ExcepitionCode.paraNullExInfo);
            }
            string retStr = string.Empty;
            errStr = string.Empty;

            string retXml = "";
            //得到地址
            string webServicAddress = GetWebServicAddress();
            //绕开信任
            if (webServicAddress.Contains("https://"))
            {
     
                //类似浏览器确认证书合法方法的绑定
                ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCallback;
            }
            //有问号认为是2016
            if (isCache2016)
            {
     

                LISService2016 curservice = Service;
                retXml = curservice.GetSQLData(SQLText, Param, session);
                pool.Put(curservice);
            }
            else
            {
     
                //创建WebService客户端代理
                LISServiceSoapClient web = new LISServiceSoapClient("LISServiceSoap", webServicAddress);
                //通过WebService查询数据
                retXml = web.GetSQLData(SQLText, Param, session);
            }
            //返回结果
            return retXml;
        }

接着就是实现主体了(用M返回的信息实现Ado.Net的接口协议)
LISAdoConnection实现连接接口都是虚操作,实际不连接

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.Common;
using LIS.DAL.ORM.DBUtility;

namespace WebserviceCacheClient
{
     
    /// 
    /// [功能描述: 通过调用Webservice实现ado的Connection]

/// [创建者: 张联珠]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class LISAdoConnection : IDbConnection, IPageData { /// /// 连接串 /// private string connectionString = ""; /// /// 页大小 /// private int pageSize = -1; /// /// 页索引 /// private int pageIndex = -1; /// /// 存行数 /// private string rowCount = ""; /// /// 构造 /// public LISAdoConnection() { } /// /// 构造 /// /// public LISAdoConnection(string connStr) { connectionString = connStr; } /// /// 开启事务 /// /// /// public IDbTransaction BeginTransaction(IsolationLevel il) { return new LISAdoTransaction(this); } /// /// 开启事务 /// /// public IDbTransaction BeginTransaction() { return new LISAdoTransaction(this); } /// /// 改变数据库 /// /// public void ChangeDatabase(string databaseName) { return; } /// /// 关闭 /// public void Close() { return; } /// /// 连接串 /// public string ConnectionString { get { return connectionString; } set { connectionString = value; } } /// /// 超时时间 /// public int ConnectionTimeout { get { return 120; } } /// /// 创建Command对象 /// /// public IDbCommand CreateCommand() { return new LISAdoCommand(); } /// /// 数据库 /// public string Database { get { return "DHC-LISDATA"; } } /// /// 打开 /// public void Open() { return; } /// /// 连接状态 /// public ConnectionState State { get { return ConnectionState.Open; } } /// /// 释放 /// public void Dispose() { return; } /// /// 存当前连接最后RowID /// public string LastRowID { get; set; } /// /// 清除连接池 /// /// public static void ClearPool(LISAdoConnection conn) { return; } /// /// 页大小 /// public int PageSize { get { return pageSize; } set { pageSize = value; rowCount = ""; } } /// /// 页索引 /// public int PageIndex { get { return pageIndex; } set { pageIndex = value; rowCount = ""; } } /// /// 行数 /// public string RowCount { get { string rowCountTMP = rowCount; rowCount = ""; pageSize = -1; pageIndex = -1; return rowCountTMP; } set { rowCount = value; } } /// /// 得到行数 /// /// public string GetRowCount() { return RowCount; } /// /// 设置分页信息 /// /// 页大小 /// 页索引 public void SetPageInfo(int sPageSize, int spageIndex) { PageSize = sPageSize; PageIndex = spageIndex; } } }

LISAdoCommand实现命令接口用返回xml实现接口约定。逻辑集中在ExecuteNonQuery、ExecuteReader、ExecuteScalar

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data;
using System.Xml;

namespace WebserviceCacheClient
{
     
    /// 
    /// [功能描述: 通过调用Webservice实现ado的Command]

/// [创建者: 张联珠]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class LISAdoCommand : IDbCommand { /// /// sql语句 /// private string commandText; /// /// 超时时间 /// private int commandTimeout = 120; /// /// sql类型 /// private CommandType commandType = CommandType.Text; /// /// 连接 /// private IDbConnection conn = null; /// /// 事务 /// private IDbTransaction transaction = null; /// /// 参数集合 /// private IDataParameterCollection parameterCollection = new LISAdoDataParameterCollection(); /// /// 取消 /// public void Cancel() { return; } /// /// sql语句 /// public string CommandText { get { return commandText; } set { commandText = value; } } /// /// 超时时间 /// public int CommandTimeout { get { return commandTimeout; } set { commandTimeout = value; } } /// /// sql类型 /// public CommandType CommandType { get { return commandType; } set { commandType = value; } } /// /// 连接 /// public IDbConnection Connection { get { return conn; } set { conn = value; } } /// /// 创建参数 /// /// public IDbDataParameter CreateParameter() { LISAdoParameter para = new LISAdoParameter(); return (DbParameter)para; } /// /// 执行更新SQL /// /// public int ExecuteNonQuery() { string err; string sql = CommandText; sql = LISAdoUtil.DealParameter(sql, this.Parameters); string xmlStr = LIS.DAL.DataAccess.WebManager.GetCacheSQLDataXML(sql, "", "", out err); if (err != "") { throw new Exception(err); } //创建一个xml文档 XmlDocument xmlDoc = new XmlDocument(); //为文档导入数据 xmlDoc.LoadXml(xmlStr); //获得根节点 XmlNode root = xmlDoc.SelectSingleNode("Response"); //得到返回值节点 XmlNode nodeReturn = root.SelectSingleNode("RetVal"); //给返回值赋值 int retVal = Convert.ToInt32(nodeReturn.InnerText); //得到返回值RowID XmlNode nodeRowID = root.SelectSingleNode("RowID"); if (nodeRowID != null) { //给返回值赋值 (this.conn as LISAdoConnection).LastRowID = nodeRowID.InnerText; } //得到错误信息 string errStr = root.SelectSingleNode("Error").InnerText; //如果错误信息不为空 if (errStr != string.Empty) { throw new Exception(err); } return retVal; } /// /// 执行查询 /// /// /// public IDataReader ExecuteReader(CommandBehavior behavior) { return ExecuteReader(); } /// /// 执行查询 /// /// public IDataReader ExecuteReader() { string err; string sql = CommandText; sql = LISAdoUtil.DealParameter(sql, this.Parameters); //得到页信息 LISAdoConnection connlis = conn as LISAdoConnection; //第二个参数给分页预留 string pagePara = connlis.PageSize+"^"+connlis.PageIndex; string xmlStr = LIS.DAL.DataAccess.WebManager.GetCacheSQLDataXML(sql, pagePara, "", out err); if (err != "") { throw new Exception(err); } //创建一个xml文档 XmlDocument xmlDoc = new XmlDocument(); //为文档导入数据 xmlDoc.LoadXml(xmlStr); //获得根节点 XmlNode root = xmlDoc.SelectSingleNode("Response"); //得到返回值节点 XmlNode nodeReturn = root.SelectSingleNode("RetVal"); //得到错误信息 err = root.SelectSingleNode("Error").InnerText; //得到返回行数 connlis.RowCount = root.SelectSingleNode("RowCount").InnerText; //给返回值赋值 int retVal = Convert.ToInt32(nodeReturn.InnerText); if (retVal == -1) { throw new Exception(err); } LISAdoDataReader dr = new LISAdoDataReader(); dr.DataDoc = xmlDoc; return dr; } /// /// 查询返回一个对象数据 /// /// public object ExecuteScalar() { string retRes = ""; string err; string sql = CommandText; if (sql.Contains("select LAST_IDENTITY() as RowID")) { return (this.conn as LISAdoConnection).LastRowID; } string paraXml = ""; //存储过程调用 if (this.commandType == CommandType.StoredProcedure) { sql = "$StoredProcedure^" + sql; paraXml = LISAdoUtil.DealParameter("", this.Parameters, true); } else { sql = LISAdoUtil.DealParameter(sql, this.Parameters); } string xmlStr = LIS.DAL.DataAccess.WebManager.GetCacheSQLDataXML(sql, paraXml, "", out err); if (err != "") { throw new Exception(err); } //创建一个xml文档 XmlDocument xmlDoc = new XmlDocument(); //为文档导入数据 xmlDoc.LoadXml(xmlStr); //获得根节点 XmlNode root = xmlDoc.SelectSingleNode("Response"); //得到返回值节点 XmlNode nodeReturn = root.SelectSingleNode("RetVal"); //给返回值赋值 int retVal = Convert.ToInt32(nodeReturn.InnerText); //得到返回值RowID XmlNode nodeRowID = root.SelectSingleNode("RowID"); if (nodeRowID != null) { //给返回值赋值 (this.conn as LISAdoConnection).LastRowID = nodeRowID.InnerText; } //结果节点 XmlNode nodeResult = root.SelectSingleNode("SQLResult"); if (nodeResult != null) { //第一个结果节点 XmlNode firstResult = nodeResult.SelectSingleNode("SQL"); if (firstResult != null) { retRes = firstResult.FirstChild.InnerText; } } //得到错误信息 string errStr = root.SelectSingleNode("Error").InnerText; //如果错误信息不为空 if (errStr != string.Empty) { throw new Exception(err); } return retRes; } /// /// 参数集合 /// public IDataParameterCollection Parameters { get { return parameterCollection; } } /// /// 准备 /// public void Prepare() { return; } /// /// 事务 /// public IDbTransaction Transaction { get { return transaction; } set { transaction = value; } } /// /// 更新行 /// public UpdateRowSource UpdatedRowSource { get { return System.Data.UpdateRowSource.None; } set { } } /// /// 释放 /// public void Dispose() { return; } } }

LISAdoDataReader实现DataReader读行数据效果及索引和字符串取结果部分

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;

namespace WebserviceCacheClient
{
     
    /// 
    /// [功能描述: 通过调用Webservice实现ado的数据读取器]

/// [创建者: 张联珠]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class LISAdoDataReader : IDataReader, IDisposable { /// /// xml文档节点 /// private XmlDocument dataDoc = null; /// /// 存结果节点 /// private XmlNodeList resNodeList = null; /// /// 当前读取位置 /// private int curIndex = 0; /// /// 结构文档 /// private XmlNode scamaNode = null; /// /// 列数 /// private int fieldCount = 0; /// /// xml文档 /// public XmlDocument DataDoc { get { return dataDoc; } set { dataDoc = value; //获得根节点 XmlNode root = dataDoc.SelectSingleNode("Response"); //结果节点 XmlNode nodeResult = root.SelectSingleNode("SQLResult"); //结果节点 resNodeList = nodeResult.ChildNodes; scamaNode = resNodeList[0].ChildNodes[0].ChildNodes[0].ChildNodes[0].ChildNodes[0].ChildNodes[0].ChildNodes[0]; fieldCount = scamaNode.ChildNodes.Count; } } /// /// 关闭 /// public void Close() { return; } /// /// 深度 /// public int Depth { get { return 1; } } /// /// 结构表 /// /// public DataTable GetSchemaTable() { throw new NotImplementedException(); } /// /// 是否关闭 /// public bool IsClosed { get { return false; } } /// /// 下一个结果 /// /// public bool NextResult() { throw new NotImplementedException(); } /// /// 读取数据 /// /// public bool Read() { curIndex++; if (curIndex < resNodeList.Count) { return true; } return false; } /// /// 影响结果 /// public int RecordsAffected { get { return 0; } } /// /// 释放 /// public void Dispose() { return; } /// /// 列行数 /// public int FieldCount { get { return fieldCount; } } public bool GetBoolean(int i) { throw new NotImplementedException(); } public byte GetByte(int i) { throw new NotImplementedException(); } public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); } public char GetChar(int i) { throw new NotImplementedException(); } public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length) { throw new NotImplementedException(); } public IDataReader GetData(int i) { throw new NotImplementedException(); } public string GetDataTypeName(int i) { throw new NotImplementedException(); } public DateTime GetDateTime(int i) { throw new NotImplementedException(); } public decimal GetDecimal(int i) { throw new NotImplementedException(); } public double GetDouble(int i) { throw new NotImplementedException(); } public Type GetFieldType(int i) { throw new NotImplementedException(); } public float GetFloat(int i) { throw new NotImplementedException(); } public Guid GetGuid(int i) { throw new NotImplementedException(); } public short GetInt16(int i) { throw new NotImplementedException(); } public int GetInt32(int i) { throw new NotImplementedException(); } public long GetInt64(int i) { throw new NotImplementedException(); } /// /// 通过位置得到名称 /// /// /// public string GetName(int i) { XmlNode nodeCol = scamaNode.ChildNodes[i]; if (nodeCol != null) { return nodeCol.Attributes["name"].Value; } else { throw new Exception("zlz查询列数没有传入的:" + i + "列"); } } public int GetOrdinal(string name) { throw new NotImplementedException(); } public string GetString(int i) { throw new NotImplementedException(); } public object GetValue(int i) { throw new NotImplementedException(); } public int GetValues(object[] values) { throw new NotImplementedException(); } public bool IsDBNull(int i) { throw new NotImplementedException(); } /// /// 中括号按名字取值 /// /// /// public object this[string name] { get { if (name == "") { return ""; } XmlNode curNode = resNodeList[curIndex]; XmlNode nodeCol = curNode.SelectSingleNode(name); if (nodeCol != null) { return nodeCol.InnerText; } else { throw new Exception("zlz查询列数没有传入的:" + name + "列"); } } } /// /// 中括号按位置取值 /// /// /// public object this[int i] { get { XmlNode curNode = resNodeList[curIndex]; XmlNodeList colList = curNode.ChildNodes; if (i >= colList.Count) { throw new Exception("zlz查询列数没有传入的:" + i + "列"); } XmlNode nodeCol = colList[i]; if (nodeCol != null) { return nodeCol.InnerText; } else { return ""; } } } } }

LISAdoDataAdapter实现适配器类,主要实现往DataSet塞数据

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Common;
using System.Data;
using System.Xml;
using System.IO;

namespace WebserviceCacheClient
{
     
    /// 
    /// [功能描述: 通过调用Webservice实现ado的DataAdapter]

/// [创建者: 张联珠]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class LISAdoDataAdapter : DbDataAdapter, IDbDataAdapter { /// /// Command对象 /// private IDbCommand command; /// /// 删除命令对象 /// new public IDbCommand DeleteCommand { get { return command; } set { command = value; } } /// /// 插入命令对象 /// new public IDbCommand InsertCommand { get { return command; } set { command = value; } } /// /// 查询命令对象 /// new public IDbCommand SelectCommand { get { return command; } set { command = value; } } /// /// 更新命令对象 /// new public IDbCommand UpdateCommand { get { return command; } set { command = value; } } /// /// 构造 /// /// public LISAdoDataAdapter(IDbCommand cmd) { command = cmd; } /// /// 构造 /// public LISAdoDataAdapter() { } /// /// 主要实现方法 /// /// /// override public int Fill(DataSet dataSet) { string err; if (command == null) { throw new Exception("zlz没有设置DataAdapter的Command对象"); } string sql = command.CommandText; sql = LISAdoUtil.DealParameter(sql, command.Parameters); //得到页信息 LISAdoConnection connlis = command.Connection as LISAdoConnection; //第二个参数给分页预留 string pagePara = connlis.PageSize + "^" + connlis.PageIndex; //第二个参数给分页预留 string xmlStr = LIS.DAL.DataAccess.WebManager.GetCacheSQLDataXML(sql, pagePara, "", out err); if (err != "") { throw new Exception(err); } //创建一个xml文档 XmlDocument xmlDoc = new XmlDocument(); //为文档导入数据 xmlDoc.LoadXml(xmlStr); //获得根节点 XmlNode root = xmlDoc.SelectSingleNode("Response"); //得到返回值节点 XmlNode nodeReturn = root.SelectSingleNode("RetVal"); //得到错误信息 err = root.SelectSingleNode("Error").InnerText; //得到返回行数 connlis.RowCount = root.SelectSingleNode("RowCount").InnerText; //给返回值赋值 int retVal = Convert.ToInt32(nodeReturn.InnerText); if (retVal == -1) { throw new Exception(err); } string dataSetXML = root.SelectSingleNode("SQLResult").OuterXml; using (StringReader xmlSR = new StringReader(dataSetXML)) { dataSet.ReadXml(xmlSR, XmlReadMode.ReadSchema); } return retVal; } /// /// 填充结构 /// /// /// /// override public DataTable[] FillSchema(DataSet dataSet, SchemaType schemaType) { throw new NotImplementedException(); } /// /// 得到参数 /// /// override public IDataParameter[] GetFillParameters() { throw new NotImplementedException(); } /// /// 丢失映射事件 /// new public MissingMappingAction MissingMappingAction { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } /// /// 丢失架构事件 /// new public MissingSchemaAction MissingSchemaAction { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } /// /// 表映射 /// new public ITableMappingCollection TableMappings { get { throw new NotImplementedException(); } } /// /// 更新 /// /// /// override public int Update(DataSet dataSet) { throw new NotImplementedException(); } } }

LISAdoTransaction实现事务对象,虚操作,不管事务,使用都是简单的地方

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace WebserviceCacheClient
{
     
    /// 
    /// [功能描述: 通过调用Webservice实现ado的事务对象]

/// [创建者: 张联珠]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class LISAdoTransaction : IDbTransaction { /// /// 连接 /// private IDbConnection conn = null; /// /// 提交 /// public void Commit() { return; } /// /// 构造 /// public LISAdoTransaction() { } /// /// 构造 /// /// public LISAdoTransaction(IDbConnection con) { conn = con; } /// /// 连接 /// public IDbConnection Connection { get { return conn; } } /// /// 级别 /// public IsolationLevel IsolationLevel { get { return IsolationLevel.Chaos; } } /// /// 回滚 /// public void Rollback() { return; } /// /// 释放 /// public void Dispose() { return; } } }

其他对象LISAdoDataParameterCollection、LISAdoParameter、LISAdoUtil

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Collections;

namespace WebserviceCacheClient
{
     
    /// 
    /// [功能描述: 通过调用Webservice实现ado的参数集合]

/// [创建者: 张联珠]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class LISAdoDataParameterCollection : IDataParameterCollection, IEnumerator { /// /// 存参数集合 /// private List<IDbDataParameter> paraList = new List<IDbDataParameter>(); /// /// 当前位置 /// private int position = -1; /// /// 释放包含指定名称参数 /// /// /// public bool Contains(string parameterName) { bool isContian = false; foreach (var p in paraList) { if (p.ParameterName == parameterName) { isContian = true; break; } } return isContian; } /// /// 指定名称参数的位置 /// /// /// public int IndexOf(string parameterName) { int index = 0; foreach (var p in paraList) { if (p.ParameterName == parameterName) { break; } index++; } return index; } /// /// 移除指定名称参数 /// /// public void RemoveAt(string parameterName) { int index = 0; int removeIndex = -1; foreach (var p in paraList) { if (p.ParameterName == parameterName) { removeIndex = index; break; } index++; } if (removeIndex > -1) { paraList.RemoveAt(removeIndex); } } /// /// 中括号按名称取数据 /// /// 名称 /// public object this[string parameterName] { get { foreach (var p in paraList) { if (p.ParameterName == parameterName) { return p; } } return null; } set { for (int i = 0; i < paraList.Count;i++ ) { if (paraList[i].ParameterName == parameterName) { paraList[i] = value as IDbDataParameter; break; } } } } /// /// 添加 /// /// /// public int Add(object value) { paraList.Add((IDbDataParameter)value); return paraList.Count(); } /// /// 清空参数 /// public void Clear() { paraList.Clear(); } /// /// 是否包含参数值 /// /// 参数值 /// public bool Contains(object value) { bool isContian = false; foreach (var p in paraList) { if (p.Value == value) { isContian = true; break; } } return isContian; } /// /// 参数值的位置 /// /// 参数值 /// public int IndexOf(object value) { int index = 0; foreach (var p in paraList) { if (p.Value == value) { break; } index++; } return index; } /// /// 在指定位置插入参数 /// /// 位置 /// 参数 public void Insert(int index, object value) { paraList.Insert(index, (IDbDataParameter)value); } /// /// 固定大小 /// public bool IsFixedSize { get { return false; } } /// /// 是否只读 /// public bool IsReadOnly { get { return false; } } /// /// 移除指定参数值 /// /// 参数 public void Remove(object value) { int index = 0; int removeIndex = -1; foreach (var p in paraList) { if (p.Value == value) { removeIndex = index; break; } index++; } if (removeIndex > -1) { paraList.RemoveAt(removeIndex); } } /// /// 移除指定位置参数 /// /// public void RemoveAt(int index) { paraList.RemoveAt(index); } /// /// 中括号按位置取参数 /// /// /// public object this[int index] { get { return paraList[index]; } set { paraList[index]=value as IDbDataParameter; } } /// /// 复制参数 /// /// /// public void CopyTo(Array array, int index) { throw new NotImplementedException(); } /// /// 得到参数数量 /// public int Count { get { return paraList.Count(); } } public bool IsSynchronized { get { return false; } } public object SyncRoot { get { throw new NotImplementedException(); } } /// /// 遍历器 /// /// public System.Collections.IEnumerator GetEnumerator() { return (IEnumerator)this; } /// /// 遍历实现 /// public object Current { get { try { return paraList[position]; } catch (IndexOutOfRangeException) { throw new InvalidOperationException(); } } } /// /// 下一个 /// /// public bool MoveNext() { position++; return (position < paraList.Count); } /// /// 重置 /// public void Reset() { position = 0; } } }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spring.Data.Common;
using System.Data;

namespace WebserviceCacheClient
{
     
    /// 
    /// [功能描述: 通过调用Webservice实现ado的参数对象]

/// [创建者: 张联珠]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class LISAdoParameter : System.Data.Common.DbParameter, IDbDataParameter { /// /// 类型 /// private DbType dbType = DbType.String; /// /// 方向 /// private ParameterDirection direction = ParameterDirection.Input; /// /// 是否空 /// private bool isNullable; /// /// 参数名称 /// private string parameterName; /// /// 大小 /// private int size; /// /// 源列 /// private string sourceColumn = ""; /// /// 映射 /// private bool sourceColumnNullMapping = false; /// /// 版本 /// private DataRowVersion sourceVersion; /// /// 参数值 /// private object paravalue; /// /// 类型 /// public override DbType DbType { get { return dbType; } set { dbType = value; } } /// /// 方向 /// public override ParameterDirection Direction { get { return direction; } set { direction = value; } } /// /// 是否空 /// public override bool IsNullable { get { return isNullable; } set { isNullable = value; } } /// /// 参数名称 /// public override string ParameterName { get { return parameterName; } set { parameterName = value; } } /// /// 重置类型 /// public override void ResetDbType() { dbType = DbType.String; } /// /// 大小 /// public override int Size { get { return size; } set { size = value; } } /// /// 源列 /// public override string SourceColumn { get { return sourceColumn; } set { sourceColumn = value; } } /// /// 映射 /// public override bool SourceColumnNullMapping { get { return sourceColumnNullMapping; } set { sourceColumnNullMapping = value; } } /// /// 版本 /// public override DataRowVersion SourceVersion { get { return sourceVersion; } set { sourceVersion = value; } } /// /// 参数值 /// public override object Value { get { return paravalue; } set { paravalue = value; } } } }
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;

namespace WebserviceCacheClient
{
     
    /// 
    /// [功能描述: 通过调用Webservice实现ado的工具类]

/// [创建者: 张联珠]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public static class LISAdoUtil { /// /// 参数和sql语句结合 /// /// sql /// 参数 /// public static string DealParameter(string sql, IDataParameterCollection Parameters, bool isGetParaStr = false) { string paraStr = ""; if (Parameters != null && Parameters.Count > 0) { int preIndex=0; int pIndex = 0; foreach (IDbDataParameter p in Parameters) { //从最后位置找问号 int index = sql.IndexOf('?', preIndex); bool isNull = false; if (isGetParaStr != true) { if (p.Value is DBNull) { p.Value = "null"; isNull = true; } else if (p.Value != null && p.Value.ToString() == String.Empty) { p.Value = ""; } else if (p.Value != null) { if (p.Value.GetType() == typeof(bool)) { if (((bool)p.Value) == true) { p.Value = "1"; } else if (((bool)p.Value) == false) { p.Value = "0"; } } else if (p.Value.GetType() == typeof(bool?)) { if (((bool)p.Value) == true) { p.Value = "1"; } else if (((bool)p.Value) == false) { p.Value = "0"; } } } else { p.Value = ""; } } if (isGetParaStr == true) { if (p.Value == null) { p.Value = ""; } if (pIndex == 0) { paraStr += p.Value.ToString(); } else { paraStr += "$ZLPS$"+p.Value.ToString(); } } else { string paraValueStr=p.Value.ToString().Replace("'","\""); if (isNull == false) { sql = sql.Substring(0, index) + "'" + paraValueStr + "'" + sql.Substring(index + 1); } else { sql = sql.Substring(0, index) + paraValueStr + sql.Substring(index + 1); } preIndex = index + paraValueStr.Length; } pIndex++; } } if (isGetParaStr == true) { return paraStr; } else { return sql; } } /// /// 创建节点 /// /// xml文档 /// 父节点 /// 节点名 /// 节点值 public static void CreateNode(XmlDocument xmlDoc, XmlNode parentNode, string name, string value) { //创建节点 XmlNode node = xmlDoc.CreateNode(XmlNodeType.Element, name, null); //给节点赋值 node.InnerText = value; //添加节点 parentNode.AppendChild(node); } } }

以上就实现了居于M调用的Ado组件,再写一个ORM的基本类就可以做到切换Ado通道不影响上层。调用稳定的话也不用随着Caché的Ado组件波动来回折腾。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using WebserviceCacheClient;

namespace LIS.DAL.Base
{
     
    /// 
    /// [功能描述: cache数据库的基础接口实现]

/// [创建者: zlz]

/// [创建时间: 2019-09-30]

/// <说明> /// /// /// <修改记录> /// <修改时间> /// <修改内容> /// /// /// ///
public class CacheBaseLIS : LIS.DAL.ORM.DBUtility.IDbFactory { /// /// 存当前连接串 /// public static string CurConnString = ""; /// /// 构造函数 /// public CacheBaseLIS() { //没强制指定连接串 if (ConnectionString == null || ConnectionString == "") { StrDbType = System.Configuration.ConfigurationSettings.AppSettings["DBType"]; ConnectionString = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString_Detail"]; if (ConnectionString == "") { //不频繁解密,浪费性能 if (CurConnString == "") { ConnectionString = LIS.DAL.Base.Util.DesUtil.DecryptDES(System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"]); CurConnString = ConnectionString; } else { ConnectionString = CurConnString; } } string ip = System.Configuration.ConfigurationSettings.AppSettings["ServiceIP"]; ConnectionString = ConnectionString.Replace("#", ip); } } /// /// 数据库类型 /// public string StrDbType { get; set; } /// /// 连接串 /// public string ConnectionString { get; set; } /// /// 返回数据库占位符 /// /// 数据库占位符 public string CreateDbParmCharacter() { return "?"; } /// /// 返回数据库连接对象 /// /// 数据库连接对象 public IDbConnection CreateDbConnection() { LISAdoConnection connCache = new LISAdoConnection(ConnectionString); //声明连接接口 IDbConnection conn = connCache; return conn; } /// /// 返回数据库命令对象 /// /// 数据库命令对象 public IDbCommand CreateDbCommand() { //声明命令接口 IDbCommand cmd = new LISAdoCommand(); return cmd; } /// /// 返回数据库适配器对象 /// /// 数据库适配器对象 public IDbDataAdapter CreateDataAdapter() { //声明数据适配器接口 IDbDataAdapter adapter = new LISAdoDataAdapter(); return adapter; } /// /// 返回数据库适配对象 /// /// 数据库命令对象 /// 数据库适配器对象 public IDbDataAdapter CreateDataAdapter(IDbCommand cmd) { //声明数据适配器接口 IDbDataAdapter adapter = new LISAdoDataAdapter((LISAdoCommand)cmd); return adapter; } /// /// 创建数据库参数 /// /// public IDbDataParameter CreateDbParameter() { //声明数据库参数接口 IDbDataParameter param = new LISAdoParameter(); return param; } /// /// 创建数据库参数数组 /// /// 大小 /// 参数数组 public IDbDataParameter[] CreateDbParameters(int size) { int i = 0; //声明数据库参数数组 IDbDataParameter[] param = null; param = new LISAdoParameter[size]; while (i < size) { param[i] = new LISAdoParameter(); i++; }; return param; } /// /// 创建数据库事务 /// /// 事务对象 public IDbTransaction CreateDbTransaction() { //根据连接串创建事务对象 IDbConnection conn = CreateDbConnection(); //如果连接是关闭的,打开连接 if (conn.State == ConnectionState.Closed) { conn.Open(); } //开始事务 return conn.BeginTransaction(); } /// /// 处理表名称 /// /// 表名称 /// 处理后的表名称 public string DealTableName(string tableName) { return tableName; } /// /// 处理属性名称 /// /// 属性名称 /// 处理后的属性名称 public string DealPropertyName(string propertyName) { return propertyName; } /// /// 清除指定连接 /// /// public void ClearPool(IDbConnection conn) { if (conn != null) { try { LISAdoConnection.ClearPool(conn as LISAdoConnection); } catch { } } } } }

配置使用新访问层
切换访问通道
本次分享经验在于面向接口编程,比如我们ORM完全面向Ado的接口实现功能,因而可以做到随数据库访问组件变化波动很小。开发的时候不关心实现细节,只关注别人的接口申明,就算是.Net的Ado一样可以直接实现接口达到一样的Ado效果。平时可以关注别人公布的接口,和自己写代码注意抽取接口公布出去(简化生活:坐公交不用关心司机怎么开到目的在的效果)达到工厂级零件组装效果。(希望有用O(∩_∩)O)

你可能感兴趣的:(设计模式,Caché)