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;
            }
			/// <summary>
        /// 清除指定连接
        /// </summary>
        /// <param name="conn"></param>
        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
{
    /// <summary>
    /// [功能描述: cache数据库的基础接口实现]<br></br>
    /// [创建者:   zlz]<br></br>
    /// [创建时间: 2015-03-15]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class CacheBase : LIS.DAL.ORM.DBUtility.IDbFactory
    {
        /// <summary>
        /// 存当前连接串
        /// </summary>
        public static string CurConnString = "";

        /// <summary>
        /// 构造函数
        /// </summary>
        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);
            }
        }

        /// <summary>
        /// 数据库类型
        /// </summary>
        public string StrDbType
        {
            get;
            set;
        }

        /// <summary>
        /// 连接串
        /// </summary>
        public string ConnectionString
        {
            get;
            set;
        }

        /// <summary>
        /// 返回数据库占位符
        /// </summary>
        /// <returns>数据库占位符</returns>
        public string CreateDbParmCharacter()
        {
            return "?";
        }

        /// <summary>
        /// 返回数据库连接对象
        /// </summary>
        /// <returns>数据库连接对象</returns>
        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;
        }

        /// <summary>
        /// 返回数据库命令对象
        /// </summary>
        /// <returns>数据库命令对象</returns>
        public IDbCommand CreateDbCommand()
        {
            //声明命令接口
            IDbCommand cmd = new CacheCommand();
            return cmd;
        }

        /// <summary>
        /// 返回数据库适配器对象
        /// </summary>
        /// <returns>数据库适配器对象</returns>
        public IDbDataAdapter CreateDataAdapter()
        {
            //声明数据适配器接口
            IDbDataAdapter adapter = new CacheDataAdapter();
            return adapter;
        }

        /// <summary>
        /// 返回数据库适配对象
        /// </summary>
        /// <param name="cmd">数据库命令对象</param>
        /// <returns>数据库适配器对象</returns>
        public IDbDataAdapter CreateDataAdapter(IDbCommand cmd)
        {
            //声明数据适配器接口
            IDbDataAdapter adapter = new CacheDataAdapter((CacheCommand)cmd);
            return adapter;
        }

        /// <summary>
        /// 创建数据库参数
        /// </summary>
        /// <returns></returns>
        public IDbDataParameter CreateDbParameter()
        {
            //声明数据库参数接口
            IDbDataParameter param = new CacheParameter();
            return param;
        }

        /// <summary>
        /// 创建数据库参数数组
        /// </summary>
        /// <param name="size">大小</param>
        /// <returns>参数数组</returns>
        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;
        }

        /// <summary>
        /// 创建数据库事务
        /// </summary>
        /// <returns>事务对象</returns>
        public IDbTransaction CreateDbTransaction()
        {
            //根据连接串创建事务对象
            IDbConnection conn = CreateDbConnection();
            //如果连接是关闭的,打开连接
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
            }
            //开始事务
            return conn.BeginTransaction();
        }

        /// <summary>
        /// 处理表名称
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <returns>处理后的表名称</returns>
        public string DealTableName(string tableName)
        {
            return tableName;
        }

        /// <summary>
        /// 处理属性名称
        /// </summary>
        /// <param name="propertyName">属性名称</param>
        /// <returns>处理后的属性名称</returns>
        public string DealPropertyName(string propertyName)
        {
            return propertyName;
        }

        /// <summary>
        /// 清除指定连接
        /// </summary>
        /// <param name="conn"></param>
        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
{
    /// <summary>
    /// [功能描述: cache数据库的基础接口实现]<br></br>
    /// [创建者:   zlz]<br></br>
    /// [创建时间: 2015-03-15]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class CacheBaseIRIS : LIS.DAL.ORM.DBUtility.IDbFactory
    {
        /// <summary>
        /// 存当前连接串
        /// </summary>
        public static string CurConnString = "";

        /// <summary>
        /// 构造函数
        /// </summary>
        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);
            }
        }

        /// <summary>
        /// 数据库类型
        /// </summary>
        public string StrDbType
        {
            get;
            set;
        }

        /// <summary>
        /// 连接串
        /// </summary>
        public string ConnectionString
        {
            get;
            set;
        }

        /// <summary>
        /// 返回数据库占位符
        /// </summary>
        /// <returns>数据库占位符</returns>
        public string CreateDbParmCharacter()
        {
            return "?";
        }

        /// <summary>
        /// 返回数据库连接对象
        /// </summary>
        /// <returns>数据库连接对象</returns>
        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;
        }

        /// <summary>
        /// 返回数据库命令对象
        /// </summary>
        /// <returns>数据库命令对象</returns>
        public IDbCommand CreateDbCommand()
        {
            //声明命令接口
            IDbCommand cmd = new IRISCommand();
            return cmd;
        }

        /// <summary>
        /// 返回数据库适配器对象
        /// </summary>
        /// <returns>数据库适配器对象</returns>
        public IDbDataAdapter CreateDataAdapter()
        {
            //声明数据适配器接口
            IDbDataAdapter adapter = new IRISDataAdapter();
            return adapter;
        }

        /// <summary>
        /// 返回数据库适配对象
        /// </summary>
        /// <param name="cmd">数据库命令对象</param>
        /// <returns>数据库适配器对象</returns>
        public IDbDataAdapter CreateDataAdapter(IDbCommand cmd)
        {
            //声明数据适配器接口
            IDbDataAdapter adapter = new IRISDataAdapter((IRISCommand)cmd);
            return adapter;
        }

        /// <summary>
        /// 创建数据库参数
        /// </summary>
        /// <returns></returns>
        public IDbDataParameter CreateDbParameter()
        {
            //声明数据库参数接口
            IDbDataParameter param = new IRISParameter();
            return param;
        }

        /// <summary>
        /// 创建数据库参数数组
        /// </summary>
        /// <param name="size">大小</param>
        /// <returns>参数数组</returns>
        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;
        }

        /// <summary>
        /// 创建数据库事务
        /// </summary>
        /// <returns>事务对象</returns>
        public IDbTransaction CreateDbTransaction()
        {
            //根据连接串创建事务对象
            IDbConnection conn = CreateDbConnection();
            //如果连接是关闭的,打开连接
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
            }
            //开始事务
            return conn.BeginTransaction();
        }

        /// <summary>
        /// 处理表名称
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <returns>处理后的表名称</returns>
        public string DealTableName(string tableName)
        {
            return tableName;
        }

        /// <summary>
        /// 处理属性名称
        /// </summary>
        /// <param name="propertyName">属性名称</param>
        /// <returns>处理后的属性名称</returns>
        public string DealPropertyName(string propertyName)
        {
            return propertyName;
        }

        /// <summary>
        /// 清除指定连接
        /// </summary>
        /// <param name="conn"></param>
        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$<Data><P3></P3><P12></P12><P4>113</P4><P0>C</P0><P8></P8><P10></P10><P5></P5><P1></P1><P13>::1</P13><P9></P9><P14>@</P14><P6></P6><P2></P2><P11></P11><P7></P7></Data>$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("<Response>")
    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("<RowID>"_rset.%RowID_"</RowID>")
    e  d
    .d objStream.Write("<SQLResult><SQL><FunRet>"_FuncRet_"</FunRet></SQL></SQLResult>")
    d objStream.Write("<RetVal>"_exeret_"</RetVal><Error>"_Err_"</Error><RowCount>"_RowCount_"</RowCount>")
    d objStream.Write("</Response>")
	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方法

/// <summary>
        /// 获得SQL数据XML
        /// </summary>
        /// <param name="SQLText">sql语句</param>
        /// <param name="Param">参数</param>
        /// <param name="session">会话信息串</param>
        /// <param name="errStr">错误信息</param>
        /// <returns>json串</returns>
        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
{
    /// <summary>
    /// [功能描述: 通过调用Webservice实现ado的Connection]<br></br>
    /// [创建者:   张联珠]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class LISAdoConnection : IDbConnection, IPageData
    {
        /// <summary>
        /// 连接串
        /// </summary>
        private string connectionString = "";

        /// <summary>
        /// 页大小
        /// </summary>
        private int pageSize = -1;

        /// <summary>
        /// 页索引
        /// </summary>
        private int pageIndex = -1;

        /// <summary>
        /// 存行数
        /// </summary>
        private string rowCount = "";

        /// <summary>
        /// 构造
        /// </summary>
        public LISAdoConnection()
        {
        }

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="connStr"></param>
        public LISAdoConnection(string connStr)
        {
            connectionString = connStr;
        }

        /// <summary>
        /// 开启事务
        /// </summary>
        /// <param name="il"></param>
        /// <returns></returns>
        public IDbTransaction BeginTransaction(IsolationLevel il)
        {
            return new LISAdoTransaction(this);
        }

        /// <summary>
        /// 开启事务
        /// </summary>
        /// <returns></returns>
        public IDbTransaction BeginTransaction()
        {
            return new LISAdoTransaction(this);
        }

        /// <summary>
        /// 改变数据库
        /// </summary>
        /// <param name="databaseName"></param>
        public void ChangeDatabase(string databaseName)
        {
            return;
        }

        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            return;
        }

        /// <summary>
        /// 连接串
        /// </summary>
        public string ConnectionString
        {
            get
            {
                return connectionString;
            }
            set
            {
                connectionString = value;
            }
        }

        /// <summary>
        /// 超时时间
        /// </summary>
        public int ConnectionTimeout
        {
            get { return 120; }
        }

        /// <summary>
        /// 创建Command对象
        /// </summary>
        /// <returns></returns>
        public IDbCommand CreateCommand()
        {
            return new LISAdoCommand();
        }

        /// <summary>
        /// 数据库
        /// </summary>
        public string Database
        {
            get { return "DHC-LISDATA"; }
        }

        /// <summary>
        /// 打开
        /// </summary>
        public void Open()
        {
            return;
        }

        /// <summary>
        /// 连接状态
        /// </summary>
        public ConnectionState State
        {
            get { return ConnectionState.Open; }
        }

        /// <summary>
        /// 释放
        /// </summary>
        public void Dispose()
        {
            return;
        }

        /// <summary>
        /// 存当前连接最后RowID
        /// </summary>
        public string LastRowID
        {
            get;
            set;
        }

        /// <summary>
        /// 清除连接池
        /// </summary>
        /// <param name="conn"></param>
        public static void ClearPool(LISAdoConnection conn)
        {
            return;
        }

        /// <summary>
        /// 页大小
        /// </summary>
        public int PageSize
        {
            get
            {
                return pageSize;
            }
            set
            {
                pageSize = value;
                rowCount = "";
            }
        }

        /// <summary>
        /// 页索引
        /// </summary>
        public int PageIndex
        {
            get
            {
                return pageIndex;
            }
            set
            {
                pageIndex = value;
                rowCount = "";
            }
        }

        /// <summary>
        /// 行数
        /// </summary>
        public string RowCount
        {
            get
            {
                string rowCountTMP = rowCount;
                rowCount = "";
                pageSize = -1;
                pageIndex = -1;
                return rowCountTMP;
            }
            set
            {
                rowCount = value;
            }
        }

        /// <summary>
        /// 得到行数
        /// </summary>
        /// <returns></returns>
        public string GetRowCount()
        {
            return RowCount;
        }

        /// <summary>
        /// 设置分页信息
        /// </summary>
        /// <param name="pageSize">页大小</param>
        /// <param name="pageIndex">页索引</param>
        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
{
    /// <summary>
    /// [功能描述: 通过调用Webservice实现ado的Command]<br></br>
    /// [创建者:   张联珠]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class LISAdoCommand : IDbCommand
    {
        /// <summary>
        /// sql语句
        /// </summary>
        private string commandText;

        /// <summary>
        /// 超时时间
        /// </summary>
        private int commandTimeout = 120;

        /// <summary>
        /// sql类型
        /// </summary>
        private CommandType commandType = CommandType.Text;

        /// <summary>
        /// 连接
        /// </summary>
        private IDbConnection conn = null;

        /// <summary>
        /// 事务
        /// </summary>
        private IDbTransaction transaction = null;

        /// <summary>
        /// 参数集合
        /// </summary>
        private IDataParameterCollection parameterCollection = new LISAdoDataParameterCollection();

        /// <summary>
        /// 取消
        /// </summary>
        public void Cancel()
        {
            return;
        }

        /// <summary>
        /// sql语句
        /// </summary>
        public string CommandText
        {
            get
            {
                return commandText;
            }
            set
            {
                commandText = value;
            }
        }

        /// <summary>
        /// 超时时间
        /// </summary>
        public int CommandTimeout
        {
            get
            {
                return commandTimeout;
            }
            set
            {
                commandTimeout = value;
            }
        }

        /// <summary>
        /// sql类型
        /// </summary>
        public CommandType CommandType
        {
            get
            {
                return commandType;
            }
            set
            {
                commandType = value;
            }
        }

        /// <summary>
        /// 连接
        /// </summary>
        public IDbConnection Connection
        {
            get
            {
                return conn;
            }
            set
            {
                conn = value;
            }
        }

        /// <summary>
        /// 创建参数
        /// </summary>
        /// <returns></returns>
        public IDbDataParameter CreateParameter()
        {
            LISAdoParameter para = new LISAdoParameter();
            return (DbParameter)para;
        }

        /// <summary>
        /// 执行更新SQL
        /// </summary>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 执行查询
        /// </summary>
        /// <param name="behavior"></param>
        /// <returns></returns>
        public IDataReader ExecuteReader(CommandBehavior behavior)
        {
            return ExecuteReader();
        }

        /// <summary>
        /// 执行查询
        /// </summary>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 查询返回一个对象数据
        /// </summary>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 参数集合
        /// </summary>
        public IDataParameterCollection Parameters
        {
            get
            {
                return parameterCollection;
            }
        }

        /// <summary>
        /// 准备
        /// </summary>
        public void Prepare()
        {
            return;
        }

        /// <summary>
        /// 事务
        /// </summary>
        public IDbTransaction Transaction
        {
            get
            {
                return transaction;
            }
            set
            {
                transaction = value;
            }
        }

        /// <summary>
        /// 更新行
        /// </summary>
        public UpdateRowSource UpdatedRowSource
        {
            get
            {
                return System.Data.UpdateRowSource.None;
            }
            set
            {

            }
        }

        /// <summary>
        /// 释放
        /// </summary>
        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
{
    /// <summary>
    /// [功能描述: 通过调用Webservice实现ado的数据读取器]<br></br>
    /// [创建者:   张联珠]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class LISAdoDataReader : IDataReader, IDisposable
    {
        /// <summary>
        /// xml文档节点
        /// </summary>
        private XmlDocument dataDoc = null;

        /// <summary>
        /// 存结果节点
        /// </summary>
        private XmlNodeList resNodeList = null;

        /// <summary>
        /// 当前读取位置
        /// </summary>
        private int curIndex = 0;

        /// <summary>
        /// 结构文档
        /// </summary>
        private XmlNode scamaNode = null;

        /// <summary>
        /// 列数
        /// </summary>
        private int fieldCount = 0;

        /// <summary>
        /// xml文档
        /// </summary>
        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;
            }
        }

        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            return;
        }

        /// <summary>
        /// 深度
        /// </summary>
        public int Depth
        {
            get
            {
                return 1;
            }
        }

        /// <summary>
        /// 结构表
        /// </summary>
        /// <returns></returns>
        public DataTable GetSchemaTable()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 是否关闭
        /// </summary>
        public bool IsClosed
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 下一个结果
        /// </summary>
        /// <returns></returns>
        public bool NextResult()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <returns></returns>
        public bool Read()
        {
            curIndex++;
            if (curIndex < resNodeList.Count)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 影响结果
        /// </summary>
        public int RecordsAffected
        {
            get
            {
                return 0;
            }
        }

        /// <summary>
        /// 释放
        /// </summary>
        public void Dispose()
        {
            return;
        }

        /// <summary>
        /// 列行数
        /// </summary>
        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();
        }

        /// <summary>
        /// 通过位置得到名称
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        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();
        }

        /// <summary>
        /// 中括号按名字取值
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        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 + "列");
                }
            }
        }

        /// <summary>
        /// 中括号按位置取值
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        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
{
    /// <summary>
    /// [功能描述: 通过调用Webservice实现ado的DataAdapter]<br></br>
    /// [创建者:   张联珠]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class LISAdoDataAdapter : DbDataAdapter, IDbDataAdapter
    {
        /// <summary>
        /// Command对象
        /// </summary>
        private IDbCommand command;

        /// <summary>
        /// 删除命令对象
        /// </summary>
        new public IDbCommand DeleteCommand
        {
            get
            {
                return command;
            }
            set
            {
                command = value;
            }
        }

        /// <summary>
        /// 插入命令对象
        /// </summary>
        new public IDbCommand InsertCommand
        {
            get
            {
                return command;
            }
            set
            {
                command = value;
            }
        }

        /// <summary>
        /// 查询命令对象
        /// </summary>
        new public IDbCommand SelectCommand
        {
            get
            {
                return command;
            }
            set
            {
                command = value;
            }
        }

        /// <summary>
        /// 更新命令对象
        /// </summary>
        new public IDbCommand UpdateCommand
        {
            get
            {
                return command;
            }
            set
            {
                command = value;
            }
        }

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="cmd"></param>
        public LISAdoDataAdapter(IDbCommand cmd)
        {
            command = cmd;
        }

        /// <summary>
        /// 构造
        /// </summary>
        public LISAdoDataAdapter()
        {
        }

        /// <summary>
        /// 主要实现方法
        /// </summary>
        /// <param name="dataSet"></param>
        /// <returns></returns>
        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;
        }

        /// <summary>
        /// 填充结构
        /// </summary>
        /// <param name="dataSet"></param>
        /// <param name="schemaType"></param>
        /// <returns></returns>
        override public DataTable[] FillSchema(DataSet dataSet, SchemaType schemaType)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 得到参数
        /// </summary>
        /// <returns></returns>
        override public IDataParameter[] GetFillParameters()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 丢失映射事件
        /// </summary>
        new public MissingMappingAction MissingMappingAction
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// 丢失架构事件
        /// </summary>
        new public MissingSchemaAction MissingSchemaAction
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// 表映射
        /// </summary>
        new public ITableMappingCollection TableMappings
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="dataSet"></param>
        /// <returns></returns>
        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
{
    /// <summary>
    /// [功能描述: 通过调用Webservice实现ado的事务对象]<br></br>
    /// [创建者:   张联珠]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class LISAdoTransaction : IDbTransaction
    {
        /// <summary>
        /// 连接
        /// </summary>
        private IDbConnection conn = null;

        /// <summary>
        /// 提交
        /// </summary>
        public void Commit()
        {
            return;
        }

        /// <summary>
        /// 构造
        /// </summary>
        public LISAdoTransaction()
        {
        }

        /// <summary>
        /// 构造
        /// </summary>
        /// <param name="con"></param>
        public LISAdoTransaction(IDbConnection con)
        {
            conn = con;
        }

        /// <summary>
        /// 连接
        /// </summary>
        public IDbConnection Connection
        {
            get { return conn; }
        }

        /// <summary>
        /// 级别
        /// </summary>
        public IsolationLevel IsolationLevel
        {
            get
            {
                return IsolationLevel.Chaos;
            }
        }

        /// <summary>
        /// 回滚
        /// </summary>
        public void Rollback()
        {
            return;
        }

        /// <summary>
        /// 释放
        /// </summary>
        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
{
    /// <summary>
    /// [功能描述: 通过调用Webservice实现ado的参数集合]<br></br>
    /// [创建者:   张联珠]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class LISAdoDataParameterCollection : IDataParameterCollection, IEnumerator
    {
        /// <summary>
        /// 存参数集合
        /// </summary>
        private List<IDbDataParameter> paraList = new List<IDbDataParameter>();

        /// <summary>
        /// 当前位置
        /// </summary>
        private int position = -1;

        /// <summary>
        /// 释放包含指定名称参数
        /// </summary>
        /// <param name="parameterName"></param>
        /// <returns></returns>
        public bool Contains(string parameterName)
        {
            bool isContian = false;
            foreach (var p in paraList)
            {
                if (p.ParameterName == parameterName)
                {
                    isContian = true;
                    break;
                }
            }
            return isContian;
        }

        /// <summary>
        /// 指定名称参数的位置
        /// </summary>
        /// <param name="parameterName"></param>
        /// <returns></returns>
        public int IndexOf(string parameterName)
        {
            int index = 0;
            foreach (var p in paraList)
            {
                if (p.ParameterName == parameterName)
                {
                    break;
                }
                index++;
            }
            return index;
        }

        /// <summary>
        /// 移除指定名称参数
        /// </summary>
        /// <param name="parameterName"></param>
        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);
            }
        }

        /// <summary>
        /// 中括号按名称取数据
        /// </summary>
        /// <param name="parameterName">名称</param>
        /// <returns></returns>
        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;
                    }

                }
            }
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="value">值</param>
        /// <returns></returns>
        public int Add(object value)
        {
            paraList.Add((IDbDataParameter)value);
            return paraList.Count();
        }

        /// <summary>
        /// 清空参数
        /// </summary>
        public void Clear()
        {
            paraList.Clear();
        }

        /// <summary>
        /// 是否包含参数值
        /// </summary>
        /// <param name="value">参数值</param>
        /// <returns></returns>
        public bool Contains(object value)
        {
            bool isContian = false;
            foreach (var p in paraList)
            {
                if (p.Value == value)
                {
                    isContian = true;
                    break;
                }
            }
            return isContian;
        }

        /// <summary>
        /// 参数值的位置
        /// </summary>
        /// <param name="value">参数值</param>
        /// <returns></returns>
        public int IndexOf(object value)
        {
            int index = 0;
            foreach (var p in paraList)
            {
                if (p.Value == value)
                {
                    break;
                }
                index++;
            }
            return index;
        }

        /// <summary>
        /// 在指定位置插入参数
        /// </summary>
        /// <param name="index">位置</param>
        /// <param name="value">参数</param>
        public void Insert(int index, object value)
        {
            paraList.Insert(index, (IDbDataParameter)value);
        }

        /// <summary>
        /// 固定大小
        /// </summary>
        public bool IsFixedSize
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 是否只读
        /// </summary>
        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }

        /// <summary>
        /// 移除指定参数值
        /// </summary>
        /// <param name="value">参数</param>
        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);
            }
        }

        /// <summary>
        /// 移除指定位置参数
        /// </summary>
        /// <param name="index"></param>
        public void RemoveAt(int index)
        {
            paraList.RemoveAt(index);
        }

        /// <summary>
        /// 中括号按位置取参数
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public object this[int index]
        {
            get
            {
                return paraList[index];
            }
            set
            {
                paraList[index]=value as IDbDataParameter;
            }
        }

        /// <summary>
        /// 复制参数
        /// </summary>
        /// <param name="array"></param>
        /// <param name="index"></param>
        public void CopyTo(Array array, int index)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// 得到参数数量
        /// </summary>
        public int Count
        {
            get
            {
                return paraList.Count();
            }
        }

        public bool IsSynchronized
        {
            get
            {
                return false;
            }
        }

        public object SyncRoot
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// 遍历器
        /// </summary>
        /// <returns></returns>
        public System.Collections.IEnumerator GetEnumerator()
        {
            return (IEnumerator)this;
        }

        /// <summary>
        /// 遍历实现
        /// </summary>
        public object Current
        {
            get
            {
                try
                {
                    return paraList[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }

        /// <summary>
        /// 下一个
        /// </summary>
        /// <returns></returns>
        public bool MoveNext()
        {
            position++;
            return (position < paraList.Count);
        }

        /// <summary>
        /// 重置
        /// </summary>
        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
{
    /// <summary>
    /// [功能描述: 通过调用Webservice实现ado的参数对象]<br></br>
    /// [创建者:   张联珠]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class LISAdoParameter : System.Data.Common.DbParameter, IDbDataParameter
    {
        /// <summary>
        /// 类型
        /// </summary>
        private DbType dbType = DbType.String;

        /// <summary>
        /// 方向
        /// </summary>
        private ParameterDirection direction = ParameterDirection.Input;

        /// <summary>
        /// 是否空
        /// </summary>
        private bool isNullable;

        /// <summary>
        /// 参数名称
        /// </summary>
        private string parameterName;

        /// <summary>
        /// 大小
        /// </summary>
        private int size;

        /// <summary>
        /// 源列
        /// </summary>
        private string sourceColumn = "";

        /// <summary>
        /// 映射
        /// </summary>
        private bool sourceColumnNullMapping = false;

        /// <summary>
        /// 版本
        /// </summary>
        private DataRowVersion sourceVersion;

        /// <summary>
        /// 参数值
        /// </summary>
        private object paravalue;

        /// <summary>
        /// 类型
        /// </summary>
        public override DbType DbType
        {
            get
            {
                return dbType;
            }
            set
            {
                dbType = value;
            }
        }

        /// <summary>
        /// 方向
        /// </summary>
        public override ParameterDirection Direction
        {
            get
            {
                return direction;
            }
            set
            {
                direction = value;
            }
        }

        /// <summary>
        /// 是否空
        /// </summary>
        public override bool IsNullable
        {
            get
            {
                return isNullable;
            }
            set
            {
                isNullable = value;
            }
        }

        /// <summary>
        /// 参数名称
        /// </summary>
        public override string ParameterName
        {
            get
            {
                return parameterName;
            }
            set
            {
                parameterName = value;
            }
        }

        /// <summary>
        /// 重置类型
        /// </summary>
        public override void ResetDbType()
        {
            dbType = DbType.String;
        }

        /// <summary>
        /// 大小
        /// </summary>
        public override int Size
        {
            get
            {
                return size;
            }
            set
            {
                size = value;
            }
        }

        /// <summary>
        /// 源列
        /// </summary>
        public override string SourceColumn
        {
            get
            {
                return sourceColumn;
            }
            set
            {
                sourceColumn = value;
            }
        }

        /// <summary>
        /// 映射
        /// </summary>
        public override bool SourceColumnNullMapping
        {
            get
            {
                return sourceColumnNullMapping;
            }
            set
            {
                sourceColumnNullMapping = value;
            }
        }

        /// <summary>
        /// 版本
        /// </summary>
        public override DataRowVersion SourceVersion
        {
            get
            {
                return sourceVersion;
            }
            set
            {
                sourceVersion = value;
            }
        }

        /// <summary>
        /// 参数值
        /// </summary>
        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
{
    /// <summary>
    /// [功能描述: 通过调用Webservice实现ado的工具类]<br></br>
    /// [创建者:   张联珠]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public static class LISAdoUtil
    {
        /// <summary>
        /// 参数和sql语句结合
        /// </summary>
        /// <param name="sql">sql</param>
        /// <param name="Parameters">参数</param>
        /// <returns></returns>
        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;
            }
        }


        /// <summary>  
        /// 创建节点  
        /// </summary>  
        /// <param name="xmlDoc">xml文档</param>  
        /// <param name="parentNode">父节点</param>  
        /// <param name="name">节点名</param>  
        /// <param name="value">节点值</param>  
        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
{
    /// <summary>
    /// [功能描述: cache数据库的基础接口实现]<br></br>
    /// [创建者:   zlz]<br></br>
    /// [创建时间: 2019-09-30]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public class CacheBaseLIS : LIS.DAL.ORM.DBUtility.IDbFactory
    {
        /// <summary>
        /// 存当前连接串
        /// </summary>
        public static string CurConnString = "";

        /// <summary>
        /// 构造函数
        /// </summary>
        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);
            }
        }

        /// <summary>
        /// 数据库类型
        /// </summary>
        public string StrDbType
        {
            get;
            set;
        }

        /// <summary>
        /// 连接串
        /// </summary>
        public string ConnectionString
        {
            get;
            set;
        }

        /// <summary>
        /// 返回数据库占位符
        /// </summary>
        /// <returns>数据库占位符</returns>
        public string CreateDbParmCharacter()
        {
            return "?";
        }

        /// <summary>
        /// 返回数据库连接对象
        /// </summary>
        /// <returns>数据库连接对象</returns>
        public IDbConnection CreateDbConnection()
        {
            LISAdoConnection connCache = new LISAdoConnection(ConnectionString);
            //声明连接接口
            IDbConnection conn = connCache;
            return conn;
        }

        /// <summary>
        /// 返回数据库命令对象
        /// </summary>
        /// <returns>数据库命令对象</returns>
        public IDbCommand CreateDbCommand()
        {
            //声明命令接口
            IDbCommand cmd = new LISAdoCommand();
            return cmd;
        }

        /// <summary>
        /// 返回数据库适配器对象
        /// </summary>
        /// <returns>数据库适配器对象</returns>
        public IDbDataAdapter CreateDataAdapter()
        {
            //声明数据适配器接口
            IDbDataAdapter adapter = new LISAdoDataAdapter();
            return adapter;
        }

        /// <summary>
        /// 返回数据库适配对象
        /// </summary>
        /// <param name="cmd">数据库命令对象</param>
        /// <returns>数据库适配器对象</returns>
        public IDbDataAdapter CreateDataAdapter(IDbCommand cmd)
        {
            //声明数据适配器接口
            IDbDataAdapter adapter = new LISAdoDataAdapter((LISAdoCommand)cmd);
            return adapter;
        }

        /// <summary>
        /// 创建数据库参数
        /// </summary>
        /// <returns></returns>
        public IDbDataParameter CreateDbParameter()
        {
            //声明数据库参数接口
            IDbDataParameter param = new LISAdoParameter();
            return param;
        }

        /// <summary>
        /// 创建数据库参数数组
        /// </summary>
        /// <param name="size">大小</param>
        /// <returns>参数数组</returns>
        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;
        }

        /// <summary>
        /// 创建数据库事务
        /// </summary>
        /// <returns>事务对象</returns>
        public IDbTransaction CreateDbTransaction()
        {
            //根据连接串创建事务对象
            IDbConnection conn = CreateDbConnection();
            //如果连接是关闭的,打开连接
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
            }
            //开始事务
            return conn.BeginTransaction();
        }

        /// <summary>
        /// 处理表名称
        /// </summary>
        /// <param name="tableName">表名称</param>
        /// <returns>处理后的表名称</returns>
        public string DealTableName(string tableName)
        {
            return tableName;
        }

        /// <summary>
        /// 处理属性名称
        /// </summary>
        /// <param name="propertyName">属性名称</param>
        /// <returns>处理后的属性名称</returns>
        public string DealPropertyName(string propertyName)
        {
            return propertyName;
        }

        /// <summary>
        /// 清除指定连接
        /// </summary>
        /// <param name="conn"></param>
        public void ClearPool(IDbConnection conn)
        {
            if (conn != null)
            {
                try
                {
                    LISAdoConnection.ClearPool(conn as LISAdoConnection);
                }
                catch
                {
                }
            }
        }
    }
}

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

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小乌鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值