对PetShop4.0数据访问层的改进
在PetShop4.0 中,系统需要处理的数据库对象分为两类:一是数据实体,对应数据库中相应的数据表。它们没有行为,仅用于表现对象的数据。这些实体类都被放到Model程 序集中,这些对象不具备持久化的功能,只是做为数据容器便于业务逻辑针对相应数据表进行读/写操作
在数据访问层,由于要对数据表进行Insert和Select操作,以SQL Server为例,就使用了SqlCommand,SqlParameter,SqlDataReader等对象,以完成这些操作。对于复杂的Parameter的传递,在PetShop中,使用了大量的字符串常量来保存参数的名称。此外,PetShop还专门为SQL Server和Oracle提供了抽象的Helper类,包装了一些常用的操作,如ExecuteNonQuery、ExecuteReader等方法。使用HELP类可以减少较多的数据库操作重复代码,Help类的方法都为静态方法,方便调用,在PetShop的DAL 层中,实现了两个不同的模块SQLServerDAL、OracleDAL,其中的区别仅在于SQLServerDAL和OracleDAL的参数类型不 同,及前者是由存储过程实现特定操作后者由SQL语句完成特定操作。我尝试改变这种较为烦琐的方式,实现SQLServer和OLEDB两种数据库通用的 一中简单架构。步骤如下:
1、对于数据库中的操作,统一由存储过程来实现。
2、规范IOper节口,由SQLHelper和OleDBHelper 实现接口,参数类型使用IDateParameter[]。
3、封装一个自定义的BookParameter类,实现IDateParameter(SqlParameter,
OledbParameter都继承自此接口,故可以在具体的Helper类中转换为具体类型的Parameter)。
4、规范工厂,通过读取Web.Config文件中所配置的数据库类型,已反射方式生产对应数据库类型的Helper类,供更上层调用。
至此,我们可以不用重复实现不同的DAL层,只需实现不同的Helper类即可
1 public interface IOper
2 {
3 int ExcuteNonQuery(string conStr,string cmdText, CommandType cmdType, IDataParameter[] paramters);
4 DataSet ExcuteGetDateSet(string conStr, string cmdText, CommandType cmdType, IDataParameter[] paramters);
5 void FillDataSet(string conStr, DataSet ds, string cmdText, CommandType cmdType, IDataParameter[] paramters, string tableName);
6 //DataTable ExecuteDataTable(string conStr, string cmdText, CommandType cmdType, IDataParameter[] paramters);
7 }
public sealed class SqlHelper:IOper{
#region ExecuteNonQuery方法
public int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText, IDataParameter[] parameters)
{
if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
//添加事务处理
int state ;
using (TransactionScope scope = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(commandText, conn);
cmd.CommandType = commandType;
AttachParameters(parameters, cmd);
state=cmd.ExecuteNonQuery();
scope.Complete();
}
catch (Exception exception)
{
state = 0;
}
}
//结束事务
if(state>0)
scope.Complete();
}
return state;}
public int ExecuteNonQuery(string connectionString, CommandType commandType, string commandText)
{
if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
return ExecuteNonQuery(connectionString, commandType, commandText, null);
}
#endregion
#region AttachParameters方法
private static void AttachParameters(IDataParameter[] parameters, SqlCommand cmd)
{
if (parameters != null && parameters.Length > 0)
{
for(int index=0;index<parameters.Length;index++)
{
if (parameters[index] is SqlParameter)
{
cmd.Parameters.Add(parameters[index]);
}
else
{
SqlParameter parameter = new SqlParameter();
parameter.DbType = parameters[index].DbType;
parameter.Value = parameters[index].Value;
parameter.ParameterName = parameters[index].ParameterName;
cmd.Parameters.Add(parameter);
}
}
}
}
#endregion
#region ExecuteDataSet方法
public DataSet ExecuteDataSet(string connectionString, CommandType commandType, string commandText, IDataParameter[] parameters, string tableName)
{
if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
DataSet ds = new DataSet();
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(commandText, conn);
AttachParameters(parameters, cmd);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds, tableName);
return ds;
}
}
public DataSet ExecuteDataSet(string connectionString, CommandType commandType, string commandText, string tableName)
{
if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
return ExecuteDataSet(connectionString, commandType, commandText, null, tableName);
}
#endregion
#region FillDataset方法
public void FillDataset(string connectionString, CommandType commandType, string commandText,
DataSet dataSet, string tableName, IDataParameter[] commandParameters)
{
if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
if (dataSet == null) throw new ArgumentNullException("dataSet");
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(commandText, conn);
if (tableName != null && tableName.Length > 0)
{
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(dataSet, tableName);
}
}
}
public void FillDataset(string connectionString, CommandType commandType, string commandText,
DataSet dataSet, string tableName)
{
FillDataset(connectionString, commandType, commandText, dataSet, tableName, null);
}
#endregion
}
工厂:
public class DataAccess
{
private static readonly string assmlyName=ConfigurationManager.AppSettings["assmlyName"];
private static readonly string className= ConfigurationManager.AppSettings["className"];
public static IOper GetDatabase(){
return (IOper)Assembly.Load(assmlyName).CreateInstance(className);
} }
通用参数类BookParameter:
public class BookParameter:IDataParameter
{
private DbType mytype;
private string myName;
private object myvalue;
private ParameterDirection direction;
private bool isNullable;
private string sourceColumn;
private DataRowVersion sourceVersion;
public BookParameter(string name, object value,DbType type)
{
this.myName = name;
this.myvalue = value;
this.isNullable = true;
this.mytype = type;
}
DbType IDataParameter.DbType
{
get { return mytype; }
set { this.mytype = value; }
}
ParameterDirection IDataParameter.Direction
{
get { return direction; }
set { direction = value; }
}
bool IDataParameter.IsNullable
{
get { return false; }
}
DataRowVersion IDataParameter.SourceVersion
{
get { return sourceVersion; }
set { sourceVersion = value; }
}
string IDataParameter.ParameterName
{
get { return this.myName; }
set { this.myName = value; }
}
object IDataParameter.Value
{
get { return myvalue; }
set { myvalue = value; }
}
string IDataParameter.SourceColumn
{
get { return sourceColumn; }
set{ sourceColumn = value;}
}
}
浙公网安备 33010602011771号