在项目开发时,有时候可能会增加或修改新的数据库,比如,刚开始我们项目用SQL Server 数据库,但后来需要用Oracle 数据库,或者说在某些情况下需要用Oracle 来代替SQL Server 数据库,甚至两种情况会同时存在,但数据库访问方面 Oracle 和SQL Server 是不同的,它们的语句写法不同,甚至所示哟哦那个的.NET Framework 数据提供程序也是不同的,那应该怎么办呢?
1. 新增数据访问层
我们不修改原来的DAL的代码,可以将原来的项目命名为SQLServerDAL,我们可以增加一个针对Oracle的DAL项目来单独实现对Oracle的访问。这样就会有两个DAL,一个用于访问SQLServer,一个用于访问Oracle。
2. 实现IDAL抽象接口
由于SQL Server 和 Oracle 对数据库的基本操作是一样的,都是增、删、改、查。所以,可以将相同的功能的操作的一系列对象抽象出来实现同一个接口:IDAL。让SQLServerDAL 的类 和OracleDAL 的类都继承这个接口。具体方法如下:
(1)添加IDAL类库项目和接口文件IManager.cs,具体代码如下(由于接口中调用Model, 所以需要添加对Model项目的引用)
//IManager.cs
namespace IDAL
{
/// <summary>
/// 接口层IManager的摘要说明
/// </summary>
public interface IManager
{
//<summary>
//增加一条数据
//</summary>
int Add(Model.Manager model);
//<summary>
//更新一条数据
//</summary>
void Update(Model.Manager model);
//<summary>
//删除一条数据
//</summary>
void Delete(string managerid);
//<summary>
//得到一个实体
//</summary>
Hui.Model.Manager GetModel(string managerid);
//<summary>
//获得数据列表
//</summary>
DataSet GetList(string managerid);
}
(2)在SQLServerDAL 和 OracleDAL 项目中添加对IDAL项目的引用,然后,SQLServerDAL 和 OracleDAL 项目中分别创建一个数据访问类:Manager,并继承自IManager的接口。
//SQLServerDAL.cs
using System.Data;
using System.Data.SqlClient;
using DBUtility;
using IDAL;
namespace SQLServerDAL
{
/// <summary>
/// Manager 数据访问类
/// </summary>
public class Manager:IManager
{
public Manager()
{
}
//<summary>
//增加一条记录
//</summary>
public int Add(Model.Manager manager)
{
return 0;
}
//<summary>
//更新一条记录
//</summary>
public void Update(Model.Manager manager)
{
}
//<summary>
//删除一条记录
//</summary>
public void Delete(string managerid)
{
}
//<summary>
//获得列表
//<summary>
public DataSet GetList(string manageid)
{
DataSet ds = new DataSet();
ds = null;
return ds;
}
///<summary>
///得到一个对象实体
///</summary>
public Model.Manager GetModel(string ManagerId)
{
StringBuilder strSql = new StringBuilder();
strSql.Append("select ID, ManagerId, PassWord");
strSql.Append(" from M_Manager");
strSql.Append(" where ManagerId = @ManagerId");
SqlParameter[] parameters = {
new SqlParameter ("@ManagerId", SqlDbType.VarChar, 20) };
parameters[0].Value = ManagerId;
Model.Manager model = new Model.Manager();
DataSet ds = DBUtility.DbHelperSQL.Query(strSql.ToString(), parameters);
if (ds.Tables[0].Rows.Count > 0)
{
if (ds.Tables[0].Rows[0]["ID"].ToString() != "")
{
model.ID = int.Parse(ds.Tables[0].Rows[0]["ID"].ToString());
}
model.ManagerId = ds.Tables[0].Rows[0]["ManagerId"].ToString();
model.PassWord = ds.Tables[0].Rows[0]["PassWord"].ToString();
return model;
}
else
{
return null;
}
}
}
}
//OracleDAL.cs
using System.Data;
using System.Data.OracleClient;
using IDAL;
using DBUtility;
namespace OracleDAL
{
//<summary>
//数据访问类
//</summary>
public class Manager : IManager
{
public Manager()
{
}
//<summary>
//添加一条记录
//</summary>
public int Add(Model.Manager model)
{
return 0;
}
//<summary>
//更新一条记录
//</summary>
public void Update(Model.Manager model)
{
}
//<summary>
//获得一个实体
//</summary>
public Model.Manager GetModel(string managerid)
{
return null;
}
//<summary>
//删除一条记录
//</summary>
public void Delete(string managerid)
{
}
//<summary>
//获得列表
//<summary>
public DataSet GetList(string manageid)
{
DataSet ds = new DataSet();
ds = null;
return ds;
}
}
}
注:在接口里定义的所有接口方法,在派生类里必须全部实现。
3. 实现抽象工厂模式
我们需要对代码进行进一步的重构和抽象,我们可以考虑用设计模式、条件外置以及反射来实现,具体方法如下:
(1)新建DALFactory类库项目,作为创建DAL对象的工厂,并新建DataAccess类放到这个抽象工厂里面去。并添加对IDAL项目的引用。
在DataAccess类中,我们创建对象通过配置文件和反射技术实现。通过配置文件的程序集名,决定加载具体的哪个DAL的程序集,动态组合类名来动态创建DAL对象,并返回IDAL接口对象,为了性能和使用方便,DataAccess类全部采用静态方法实现。
//DataAccess.cs
using IDAL;
using System.Reflection;
using System.Configuration;
namespace DALFactory
{
//<summary>
//在抽象工厂中创建DAL对象
//</summary>
public sealed class DataAccess
{
private static readonly string AssemblyPath = ConfigurationManager.AppSettings["DAL"];
//<summary>
//创建数据层接口
//</summary>
public static IDAL.IManager CreateManager()
{
string classNamespace = AssemblyPath + ".Manager"; //类名称
object objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace); // 反射
return (Hui.IDAL.IManager)objType; //类型转换
}
}
(2)实现条件外置,即通过配置文件来实现对数据访问层的判断。我们可以把需要使用的DAL类型信息放在配置文件中,然后根据配置文件来选择创建具体的对象(DAL)。
在Web.config配置文件中增加当前数据访问层的信息:
<appSettings>
<add key="DAL" value="SQLServerDAL"/>
</appSettings>
此外,由于反射是一种非常耗费性能的操作。所以,我们可以通过缓存的方式来进行处理。DataAccess代码改为如下:
//DadaAccess.cs
//使用缓存
private static object CreateObject(string AssemblyPath, string classNamespace)
{
object objType = DataCache.GetCache(classNamespace); //从缓存获取对象
if (objType == null) //缓存中没有
{
try
{
//创建
objType = Assembly.Load(AssemblyPath).CreateInstance(classNamespace);
DataCache.SetCache(classNamespace, objType); // 写入缓存
}
catch
{
}
}
return objType;
}
//<summary>
//创建数据访问层
//</summary>
public static IDAL.IManager CreateManager()
{
string classNamespace = AssemblyPath + ".Manager";
object objType = CreateObject(AssemblyPath, classNamespace);
return (IDAL.IManager)objType;
}
(3)为BLL项目添加对IDAL 和 DALFactory项目的引用。在BLL层中通过DALFactory 来创建DAL对象的接口调用,而不用关心具体该调用哪个DAL对象。BLL代码如下:
//BLLManager.cs
namespace BLL
{
/// <summary>
/// 业务逻辑类Manager
/// </summary>
public class Manager
{
//从工厂里面创建数据访问类
IDAL.IManager dal = .DALFactory.DataAccess.CreateManager();
public Manager()
{
}
///<summary>
///查询一条数据
///</summary>
public Model.Manager GetModel(string ManagerId)
{
return dal.GetModel(ManagerId);
}
//其他代码省略。。。。。。。。。。
}
}