什么是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$113 C ::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)