打造自己的数据访问层(一)
项目开发中,大多数开发人员的核心工作就是如何对数据进行存储及访问。为了进行数据操作,我们首先得解决几个基本问题:
1、如何与一个数据库建立连接。
2、如何从数据库读取相应的数据。
3、如何对数据表进行增改操作。
.NET中,ADO.NET很方便的解决了上面三个问题,我们可以使用DbConnection进行连接,DataSet进行数据存储,DataAdapter进行数据更新。先看一段代码:
//创建DbConnection对象连接数据库
SqlConnection conn = new SqlConnection();
conn.ConnectionString = "server=.;uid=sa;password=123456; database=DATA_BASE; max pool size=300;";
//创建DataAdapter、Command对象,读取数据
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT * FROM TEST";
da.SelectCommand = cmd;
//创建DataSet对象,存储数据,建立与物理表的映射
DataSet ds = new DataSet();
da.Fill(ds, "TEST");
上述代码实现对数据库“DATA_BASE”中“TEST”表数据读取,并用DataSet时行存储。
既然读出了TEST表中的数据,接下来要解决的就是如何对TEST表进行增、删、改操作。
为实现增、删、改操作,需要为DataAdapter指定InsertCommand、DeleteCommand以及UpdateCommand,并为每个Command对象绑定参数:
//新增数据
cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "INSERT INTO TEST (ID, NAME, VAL) VALUES (@ID, @NAME, @VAL)";
SqlParameter param = new SqlParameter("@ID", null);
param.SourceColumn = "ID";
cmd.Parameters.Add(param);
param = new SqlParameter("@NAME", null);
param.SourceColumn = "NAME";
cmd.Parameters.Add(param);
param = new SqlParameter("@VAL", null);
param.SourceColumn = "VAL";
cmd.Parameters.Add(param);
da.InsertCommand = cmd;
//修改数据
cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "UPDATE TEST SET NAME = @NAME, VAL = @VAL WHERE ID = @ID";
param = new SqlParameter("@ID", null);
param.SourceColumn = "ID";
cmd.Parameters.Add(param);
param = new SqlParameter("@NAME", null);
param.SourceColumn = "NAME";
cmd.Parameters.Add(param);
param = new SqlParameter("@VAL", null);
param.SourceColumn = "VAL";
cmd.Parameters.Add(param);
da.UpdateCommand = cmd;
//删除数据
cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "DELETE FROM TEST WHERE ID = @ID";
param = new SqlParameter("@ID", null);
param.SourceColumn = "ID";
cmd.Parameters.Add(param);
da.DeleteCommand = cmd;
完成准备工作后,利用DataTable进行数据操作:
DataTable dt = ds.Tables["TEST"];
dt.PrimaryKey = new DataColumn[] { dt.Columns["ID"] };
dt.Rows.Add(new object[]{
Guid.NewGuid().ToString(), string.Format("测试:{0}", DateTime.Now), string.Format("测试值:{0}", DateTime.Now)
});
DataRow dr = dt.Rows.Find("f8dc2c64-f51a-4e99-bde1-a20069b09c3a");
if (dr != null)
{
dr["NAME"] = string.Format("测试修改:{0}", DateTime.Now);
}
dr = dt.Rows.Find("ed7d079b-81ec-4ba4-bf85-688621e495e7");
if (dr != null)
{
dr.Delete();
}
最后调用DataAdapter的Update方法保存变更后的数据:
da.Update(ds, "TEST");
利用ADO.NET的上述方法,我们已经完成了对数据库的完整操作。
注:上述代码是利用DataAdapter对数据库进行读写的基本原理,非常重要,我们后面的改造都将以此作为依据。
虽然我们已经能完成对数据的操作,但现实际上还是存在很多问题:
1、我们只是对MSSql数据库进行操作,如果要对Oracle或MySql进行操作我们得定义新的Oracle或MySql数据对象,如果能由系统自动判断操作的数据库类型,我们就能省去对数据对象的关注。
2、我们做了太多的准备工作,我们只对一张表进行操作,如查我们要对多张表进行操作,参数又很多,实际上会产生大量的重复代码,我们得考虑消除这些代码。
对于上述问题,如果我们自己实现一个数据访问层,对ADO.NET对象进行封装,只关注实际的数据的操作,而不关注系统是如何与数据库进行连接、如何进行参数传递,那我们的需求就算基本满足了。
我们可以先进行假设,需要达成如下效果,以伪码的形式给出:
创建数据执行者:DataExecuter:execObj;
创建数据映射对象:DataMapping map;
由映射对象填充数据集:map.Fill(sqlText, "TEST", ds);
设置映射对象更新命令:map.SetCommands(Insert | Update | Delete, ds);
DataTable进行实际增、删、改操作。
数据执行者执行最后的变更操作:execObj.Update(ds);
后面我将一步步看到上述假设是如何实现的。