6.11 提供程序无关的代码
大多数情况下,ADO.NET提供程序模型是处理不同数据源的理想解决方案,它允许数据库厂商开发自己优化的解决方案的同时又保证了高层次的一致性。这样,熟练的开发人员不必重新学习基础知识。但是有时候,我们更加希望自己所写的程序能够与具体的ADO.NET提供程序无关,它可以在所有的ADO.NET提供程序中运行,从而可以具有更高复用价值。这时,就可以使用创建工厂的形式来实现这样的要求。
System. Data.Common.DbProviderFactories类提供了一个静态的GetFactory()方法,该方法会根据提供程序的名字(如System.Data.SqlClient、System.Data.OracleClient)来返回响应的工厂。使用示例如下面的代码所示:
DbProviderFactory dbProviderFactory
=DbProviderFactories.GetFactory("System.Data.SqlClient")
拥有一个工厂之后,就可以使用DbProviderFactory.CreateXxx()方法(如Create Connection()、CreateCommand()、CreateParameter()与CreateDataAdapter())来创建相应的对象。创建示例如下面的代码所示:
创建一个连接:
DbConnection dbConnection=dbProviderFactory.CreateConnection();
创建一个命令:
DbCommand cmd=dbProviderFactory.CreateCommand()
代码清单6-6封装了一个完整的与提供代码无关的数据操作类,可以直接使用它来做相关的数据处理。
代码清单6-6 DbHelper.cs
using System;
using System.Data;
using System.Configuration;
using System.Web.UI.WebControls;
using System.Data.Common;
using System.Globalization;
namespace_6_5
{
region委托
///<summary>
///数据库操作命令委托
///</summary>
///<param name="command">操作命令</param>
///<returns>委托的命令</returns>
public delegate object CommandDelegate(DbCommand dbcommand);
///<summary>
///DbDataReader命令委托
///</summary>
///<param name="dbDataReader">DbDataReader</param>
public delegate void DBDataReaderDelegate(DbDataReader
dbDataReader);
endregion
///<summary>
///数据库操作的辅助类
///</summary>
public class DbHelper
{
region字段
private static DbHelper instance;
private ConnectionStringSettings connectionStringSettings=null;
private DbProviderFactory dbProviderFactory=null;
///<summary>
///保存数据库链接字符串
///</summary>
public static string DataConnenctString="ConnectString";
endregion
region构造函数
public DbHelper()
{
connectionStringSettings=
ConfigurationManager.ConnectionStrings
[DataConnenctString];
if(connectionStringSettings!=null)
{
if(!string.IsNullOrEmpty(
connectionStringSettings.ProviderName)
&&!string.IsNullOrEmpty(
connectionStringSettings.ConnectionString))
dbProviderFactory=
DbProviderFactories.GetFactory(
connectionStringSettings.ProviderName);
}
}
///<summary>
///构造函数
///</summary>
///<param name="DbConnectSettingName">连接字符串名称</param>
public DbHelper(string dbConnectSettingName)
{
if(string.IsNullOrEmpty(dbConnectSettingName))
{
dbConnectSettingName=DataConnenctString;
}
connectionStringSettings=
ConfigurationManager.ConnectionStrings
[dbConnectSettingName];
if(connectionStringSettings!=null)
{
if(!string.IsNullOrEmpty(
connectionStringSettings.ProviderName)
&&!string.IsNullOrEmpty(
connectionStringSettings.ConnectionString))
dbProviderFactory=
DbProviderFactories.GetFactory
((cnnectionStringSettings.ProviderName);
}
}
endregion
region类属性
public static DbHelper Instance
{
get
{
if(instance==null)
instance=new DbHelper("");
return instance;
}
}
endregion
region类实例属性
public string ConnectString
{
get{return
connectionStringSettings.ConnectionString;}
}
public DbProviderFactory ProviderFactory
{
get{return dbProviderFactory;}
}
public string ProviderString
{
get{return connectionStringSettings.ProviderName;}
}
endregion
///<summary>
///创建一个数据库连接
///</summary>
///<returns></returns>
public DbConnection CreateConnection()
{
if(dbProviderFactory==null)
{
return null;
}
else
{
DbConnection dbConnection=
dbProviderFactory.CreateConnection();
dbConnection.ConnectionString=
connectionStringSettings.ConnectionString;
return dbConnection;
}
}
///<summary>
///执行无结果集Sql
///</summary>
///<param name="commandType">命令类型</param>
///<param name="sql">Sql语句</param>
///<returns>影响的记录数</returns>
public int ExecuteNonQuery(CommandType commandType,
string sql)
{
CommandDelegate cd=delegate(DbCommand cmd)
{
try
{
return cmd.ExecuteNonQuery();
}
catch
{
return-1;
}
};
return(int)ExecuteCmdCallback(commandType, sql, cd);
}
///<summary>
///执行带参数的非查询语句
///</summary>
///<param name="commandType">命令类型</param>
///<param name="sql">Sql语句</param>
///<param name="para">参数集合</param>
///<returns>影响的记录数</returns>
public int ExecuteNonQuery(CommandType commandType,
string sql, DbParameter[]para)
{
CommandDelegate cd=delegate(DbCommand cmd)
{
return cmd.ExecuteNonQuery();
};
return(int)ExecuteCmdCallback(commandType, sql, cd, para);
}
///<summary>
///执行带参数与委托命令的查询语句,并返回相关的委托命令
///</summary>
///<param name="commandType">命令类型</param>
///<param name="sql">Sql语句</param>
///<param name="commandDelegate">委托类型</param>
///<param name="para">参数集合</param>
///<returns>委托的命令</returns>
private object ExecuteCmdCallback(CommandType commandType,
string sql, CommandDelegate commandDelegate,
DbParameter[]para)
{
using(DbConnection dbCnn=CreateConnection())
{
using(DbCommand cmd=
dbProviderFactory.CreateCommand())
{
cmd.CommandType=commandType;
cmd.CommandText=sql;
cmd.Connection=dbCnn;
for(int i=0;i<para.GetLength(0);i++)
{
cmd.Parameters.Add(para[i]);
}
dbCnn.Open();
return commandDelegate(cmd);
}
}
}
///<summary>
///通过DbDataReader来读取数据
///</summary>
///<param name="sql">Sql语句</param>
///<param name="readdelegate">DBDataReaderDelegate</param>
public bool ReadData(string sql,
DBDataReaderDelegate readdelegate)
{
bool result=false;
CommandDelegate cd=delegate(DbCommand cmd)
{
using(DbDataReader dbReader=cmd.ExecuteReader())
{
readdelegate(dbReader);
return true;
}
};
result=((bol)ExecuteCmdCallback(CommandType.Text, sql, cd);
return result;
}
private object ExecuteCmdCallback(CommandType commandType,
string sql, CommandDelegate commandDelegate)
{
using(DbConnection dbCon=CreateConnection())
{
using(DbCommand cmd=
dbProviderFactory.CreateCommand())
{
cmd.CommandType=commandType;
cmd.CommandText=sql;
cmd.Connection=dbCon;
dbCon.Open();
return commandDelegate(cmd);
}
}
}
private object ExecuteCmdCallback(CommandType commandType,
CommandDelegate commandDelegate)
{
using(DbConnection dbCon=CreateConnection())
{
using(DbCommand cmd=
dbProviderFactory.CreateCommand())
{
cmd.Connection=dbCon;
cmd.CommandType=commandType;
dbCon.Open();
return commandDelegate(cmd);
}
}
}
///<summary>
///根据Sql创建一个DataTable结果集
///</summary>
///<param name="commandType">命令类型</param>
///<param name="sql">Sql语句</param>
///<returns>DataTable</returns>
public DataTable CreateDataTable(CommandType commandType,
string sql)
{
CommandDelegate cd=delegate(DbCommand cmd)
{
using(DbDataReader dr=cmd.ExecuteReader())
{
DataTable dt=new DataTable();
dt.Locale=CultureInfo.InvariantCulture;
dt.Load(dr);
return dt;
}
};
return(DataTable)ExecuteCmdCallback(CommandType.Text, sql, cd);
}
///<summary>
///执行查询,并返回查询所返回的结果集中第一行的第一列
///</summary>
///<param name="sql">Sql语句</param>
///<returns>结果集中第一行的第一列</returns>
public string GetValue(string sql)
{
CommandDelegate cd=delegate(DbCommand cmd)
{
return cmd.ExecuteScalar();
};
object value=ExecuteCmdCallback(CommandType.Text, sql, cd);
if(value==null)
return"";
return value.ToString();
}
///<summary>
///执行查询,并返回查询所返回的结果集中第一行的第一列
///</summary>
///<param name="sql">Sql语句</param>
///<returns>结果集中第一行的第一列</returns>
public Object GetObject(string sql)
{
CommandDelegate cd=delegate(DbCommand cmd)
{
return cmd.ExecuteScalar();
};
return ExecuteCmdCallback(CommandType.Text, sql, cd);
}
///<summary>
///根据Sql语句创建一个DataSet类型的结果集
///</summary>
///<param name="commandType">命令类型</param>///<param name="sql">Sql语句</param>
///<returns>相关数据集</returns>
public DataSet CreateDataSet(CommandType commandType,
string sql)
{
CommandDelegate cd=delegate(DbCommand cmd)
{
using(DbDataAdapter da=
dbProviderFactory.CreateDataAdapter())
{
DataSet ds=new DataSet();
ds.Locale=CultureInfo.InvariantCulture;
da.SelectCommand=cmd;
da.Fill(ds);
return ds;
}
};
return(DataSet)ExecuteCmdCallback(CommandType.Text, sql, cd);
}
}
}
创建好这个数据操作类之后,就可以通过配置不同的providerName来使用不同的数据库。如果是使用SQL Server数据库,可以在配置文件(如Web.config)里做如下连接配置。如下面的代码所示:
<connectionStrings>
<add name="ConnectString"
connectionString="server=.;
database=ASPNET4;uid=sa;pwd=mawei;"
providerName="System.Data.SqlClient"/>
</connectionStrings>
这样,DbHelper类的构造函数会根据连接字符串中的providerName(如System.Data.SqlClient)来创建相应的提供程序。如果将SQL Server数据库换成Oracle数据库,则只需要在配置文件Web.config里做如下连接配置就可以了,而不必重写DbHelper类。如下面的代码所示:
<connectionStrings>
<add name="ConnectString"
connectionString="Data Source=ASPNET4;
Persist Security Info=True;User ID=mawei;
Password=mawei;Unicode=True"
providerName="System.Data.OracleClient"/>
</connectionStrings>
DbHelper类的使用方法很简单,使用示例如下面的代码所示:
DbHelper db=new DbHelper();
DataSet ds=db.CreateDataSet(CommandType.Text,
"select*from employee");
//或者DataSet ds=DbHelper.Instance.CreateDataSet
//((CmmandType.Text,"select*from employee");
GridView1.DataSource=ds;
GridView1.DataBind();