由于项目需要适用于Sybase 9.1.2和Sql Server 2000的数据库,刚开始使用DAAB3.1的Odbc来操作数据库,但总觉得不是十分灵活,而且Odbc连接Sql Server 2000效率也不高;
再者,我也想项目能够提供对Oracle的支持
。感谢天行者的daab3.1使用笔记,这篇文章介绍了如何通过只修改配置文件而不改动代码的情况下实现数据库的转换。
<configSections>
<section name="daabProviders" type="GotDotNet.ApplicationBlocks.Data.DAABSectionHandler, GotDotNet.ApplicationBlocks.Data">
</section>
</configSections>
<daabProviders>
<daabProvider alias="misapp" assembly="GotDotNet.ApplicationBlocks.Data" type="GotDotNet.ApplicationBlocks.Data.SqlServer" />
</daabProviders>
在代码中只要这样写 AdoHelper helper = AdoHelper.CreateHelper("misapp");
但是这里我有两个问题:
一、在天行者的文章里没有介绍我们怎么实例化一个IDbConnection,这在启用外部事务的时候是必须的。这点看起来比较好解决,我们可以写一个CreateConnection的工厂方法。
二、天行者的文章里也没有提到如何实例化IDataParameter,因为他是通过ADOHelper.GetSpParameterSet来得到IDataParameter的个数和类型。但如果ADOHelper.GetSpParameterSet不能使用怎么办?这种情况确实存在,比如说在Sybase 9.1.2下就行不通,具体请参见我的另一篇文章 使用DAAB 3.1连接Sybase ASE 11.9.2数据库的两个问题(原创)在这种情况下我们只能自己实例化IDataParameter。(修改于2006/07/07,由于使用OracleClient连接Oracle,其中同Odbc连接有很大的差异,比方说返回结果集只能用ref cursor,而且对于存储过程来说ExecuteScalar不能使用,因此,我们AdoHelper.ExecuteScalar方法不是通用的,因此下面的代码已经取消了对Oracle的支持)
下面是我自己写的实现上述两个问题的代码,代码未经过详细测试,本人不承担使用该代码的任何后果。
public
enum
DatabaseType:
byte
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
Sybase = 1,
MSSqlServer2000 = 2,
//Oracle = 3,
MSServerODBC=4
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
}
![None.gif](/Images/OutliningIndicators/None.gif)
public
class
DataAccessConfigMgr
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
public static string GetXTERPCURBSConnStr()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
return ConfigurationSettings.AppSettings["SQLconnstr"];
}
public static DatabaseType GetXTERPCURBSDBType()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
string dbType= ConfigurationSettings.AppSettings["DatabaseType"];
if(dbType.ToUpper().IndexOf("SYBASE")!=-1)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return DatabaseType.Sybase;
}
else if (dbType.ToUpper().IndexOf("MSSQLSERVER2000")!=-1)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return DatabaseType.MSSqlServer2000;
}
else if (dbType.ToUpper().IndexOf("ORACLE")!=-1)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return DatabaseType.Oracle;
}
else if (dbType.ToUpper().IndexOf("MSSERVERODBC")!=-1)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return DatabaseType.MSServerODBC;
}
throw new Exception("don't know this database type");
}
}
public
enum
XTERPType
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
这里定义XTERPType枚举,使用者只需要将XTERPType枚举作为
参数传递给CreateDataParameter方法,减少了出错的可能。
如果出现枚举不一致的情况,如C#的Decimal在Odbc中需要映射为
OdbcType.Double而不是OdbcType.Decimal,而在SqlServer中可以
使用SqlDbType.Decimal。因此我们使用XTERPType.Decimal根据
不同的数据库映射为不同的枚举,在DBFactory.CreateDataParameter
方法中会有体现。这里我们只给出几种常用的数据类型,并且对于在
Oracle下并没有具体的测试,如果有不一致的情况,请参照Odbc中对
OdbcType.Double的处理方法。
*/
Char = 1,
DateTime = 2,
Decimal = 3,
Int = 4,
VarChar = 5
}
![None.gif](/Images/OutliningIndicators/None.gif)
public
class
DBFactory
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
private static DatabaseType dbType=DataAccessConfigMgr.GetXTERPCURBSDBType();
private DBFactory()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
}
public static IDbConnection CreateConnection(string connstr)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
switch (dbType)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case DatabaseType.Sybase:
return new OdbcConnection(connstr);
case DatabaseType.MSSqlServer2000:
return new SqlConnection(connstr);
//case DatabaseType.Oracle:
// return new OracleConnection(connstr);
case DatabaseType.MSServerODBC:
return new OdbcConnection(connstr);
}
throw new Exception("don't know this database type");
}
public static IDbConnection CreateConnection()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return CreateConnection(DataAccessConfigMgr.GetXTERPCURBSConnStr());
}
public static IDataParameter CreateDataParameter(string parameterName,XTERPType type)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
IDataParameter param;
Type xtType=typeof(XTERPType);
Type sysType;
Enum dbtype;
switch(dbType)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case DatabaseType.Sybase:
sysType=typeof(OdbcType);
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//*
Enum.GetName(xtType,type)得到传递的XTERPType枚举的字符串,然后
通过Enum.Parse(sysType,Enum.GetName(xtType,type))将一个枚举常数
的名称表示转换成等效的枚举对象,由于得到的是Object,我们还需要
强制转换为相应的枚举类型。在这里,我们会对不一致的情况进行判断修改
如:Odbc中采用OdbcType.Double而不是OdbcType.Decimal,我们通过判断
传递的XTERPType枚举是否为XTERType.Decimal来决定是否修改为合适的枚举
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
*/
dbtype=(OdbcType)Enum.Parse(sysType,Enum.GetName(xtType,type));
param=new OdbcParameter();
param.ParameterName=parameterName;
if(type.Equals(XTERPType.Decimal))
((OdbcParameter)param).OdbcType=OdbcType.Double;
else
((OdbcParameter)param).OdbcType=(OdbcType)dbtype;
return param;
case DatabaseType.MSSqlServer2000:
sysType=typeof(SqlDbType);
dbtype=(SqlDbType)Enum.Parse(sysType,Enum.GetName(xtType,type));
string s=Enum.Format(sysType, Enum.Parse(sysType,Enum.GetName(xtType,type)), "d");
param=new SqlParameter();
param.ParameterName=parameterName;
((SqlParameter)param).SqlDbType=(SqlDbType)dbtype;
return param;
case DatabaseType.MSServerODBC:
sysType=typeof(OdbcType);
dbtype=(OdbcType)Enum.Parse(sysType,Enum.GetName(xtType,type));
param=new OdbcParameter();
param.ParameterName=parameterName;
if(type.Equals(XTERPType.Decimal))
((OdbcParameter)param).OdbcType=OdbcType.Double;
else
((OdbcParameter)param).OdbcType=(OdbcType)dbtype;
return param;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
}
throw new Exception("Can't create correct parameter");
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
}
}
在web.config配置如下
<
configSections
>
<
section
name
="daabProviders"
type
="GotDotNet.ApplicationBlocks.Data.DAABSectionHandler, GotDotNet.ApplicationBlocks.Data"
>
</
section
>
</
configSections
>
<
daabProviders
>
<!--
<daabProvider alias="misapp" assembly="GotDotNet.ApplicationBlocks.Data" type="GotDotNet.ApplicationBlocks.Data.SqlServer" />
-->
<
daabProvider
alias
="misapp"
assembly
="GotDotNet.ApplicationBlocks.Data"
type
="GotDotNet.ApplicationBlocks.Data.Odbc"
/>
</
daabProviders
>
<
appSettings
>
<!--
设置DatabaseType,系统判断是否包含Sybase,MSSqlServer2000,MSServerOdbc,Oracle创建相应的IDbConnection和IDataParameter
Oracle未测试
-->
<
add
key
="DatabaseType"
value
="Sybase 9.1.2"
/>
<!--
<add key="DatabaseType" value="MSSqlServer2000" />
-->
<!--
<add key="DatabaseType" value="MSServerOdbc" />
-->
<!--
设置相应的字符串
-->
<!--
Sybase ODBC
-->
<
add
key
="SQLconnstr"
value
="Driver={SYBASE SYSTEM 11};Srvr=basil;Database=XTERPCURBS;Uid=sa;pwd="
/>
<!--
SqlServer ODBC
-->
<!--
<add key="SQLconnstr" value="Driver={SQL Server};Server=basil;Database=XTERPCURBS;Trusted_Connection=yes;Uid=sa;pwd=" />
-->
<!--
SqlServer SqlClient
-->
<!--
<add key="SQLconnstr" value="server=localhost;database=XTERPCURBS;uid=sa;pwd=;" />
-->
<!--
<add key="SQLconnstr" value="Provider=SQLOLEDB;Data Source=basil;Initial Catalog=test;Integrated Security=SSPI" />
-->
</
appSettings
>
在代码中这样使用:
private
GDN.AdoHelper helper
=
GDN.AdoHelper.CreateHelper(
"
misapp
"
);
using
( IDbConnection conn
=
DBFactory.CreateConnection(DataAccessConfigMgr.GetXTERPCURBSConnStr()))
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
conn.Open();
IDbTransaction transaction=conn.BeginTransaction();
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
try
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
IDataParameter [] searchParms = new IDataParameter[1];
searchParms[0] = DBFactory.CreateDataParameter("@bh",XTERPType.VarChar);
searchParms[0].Value = bh;
helper.ExecuteNonQuery(transaction,"delYsqlBxMx",searchParms);
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
foreach(DataRow dr in BXCredDS.Tables[BaoXiaoPingZhengData.BAOXIAOMINGXI_TABLE].Rows)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
searchParms = new IDataParameter[4];
searchParms[0]=DBFactory.CreateDataParameter("@bh",XTERPType.VarChar);
searchParms[1]=DBFactory.CreateDataParameter("@xh",XTERPType.Int);
searchParms[2]=DBFactory.CreateDataParameter("@code",XTERPType.VarChar);
searchParms[3]=DBFactory.CreateDataParameter("@je",XTERPType.Decimal);
searchParms[0].Value=bh;
searchParms[1].Value=Convert.ToInt32(dr[BaoXiaoPingZhengData.XUHAO_FIELD]);
searchParms[2].Value=dr[BaoXiaoPingZhengData.CODE_FIELD].ToString();
searchParms[3].Value=Convert.ToDecimal(dr[BaoXiaoPingZhengData.SUM_FIELD]);
helper.ExecuteNonQuery(transaction,"insertYsqlBxMx",searchParms);
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
transaction.Commit();
conn.Close();
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
}
catch(Exception ex)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
transaction.Rollback();
conn.Close();
throw ex;
}
}