1. ORM数据库操作原理
前面已经介绍过了个人ORM映射框架中的三个核心库:
实体—数据库 映射特性关系:
http://www.cnblogs.com/qingyuan/archive/2010/04/02/1702998.html
实体分析器:
http://www.cnblogs.com/qingyuan/archive/2010/04/05/1704546.html
Sql 语句生成组建:
http://www.cnblogs.com/qingyuan/archive/2010/04/16/1713658.html
至于这篇文章也就是这四个组件中的最后一个了------- 数据库操作库。目前.net 中对于数据库操作的模板或组件太多了,先不说微软的Linq to SQL,Linq to Entity, 还有开源组织的Hibernate 克隆版NHibernate,以及前些天突然冒出来的ALinq, 号称压过Linq,有时间再研究一下。其实这些看是强大的组件框架,在其外表下面都是如出一辙,他们都是在ADO.NET 中进行的封装。
不过在这个数据库操作中,都是ADO.NET进行数据库操作,但是对于对象的查询,都是泛化了的类型,也就是说我们不知道具体查询的是那张表,或者说是查询结果集是封装到那个对象,这就是本文要解决的问题。
2. ADO.NET 介绍
感觉在这里进行ADO.NET的讲解似乎是多次一举,我相信ADO.NET是每个asp.net 程序员必会的基本技能。但是这里还是简单介绍其五个核心对象吧。
Connection: Connection 对象主要是开启程序和数据库之间的连结。没有利用连结对象将数据库打开,是无法从数据库中取得数据的。
Command:Command 对象主要可以用来对数据库发出一些指令,例如可以对数据库下达查询、新增、修改、删除数据等指令,以及呼叫存在数据库中的预存程序等。
DataAdapter: DataSetCommand 对象主要是在数据源以及DataSet 之间执行数据传输的工作,它可以透过Command 对象下达命令后,并将取得的数据放入DataSet 对象中。
DataSet:DataSet 这个对象可以视为一个暂存区(Cache),可以把从数据库中所查询到的数据保留起来,甚至可以将整个数据库显示出来。DataSet 的能力不只是可以储存多个Table 而已,还可以透过DataSetCommand 对象取得一些例如主键等的数据表结构,并可以记录数据表间的关联。DataSet 对象可以说是ADO.NET 中重量级的对象,这个对象架构在DataSetCommand 对象上,本身不具备和数据源沟通的能力。
DataReader: 当我们只需要循序的读取数据而不需要其它操作时,可以使用DataReader 对象。DataReader对象只是一次一笔向下循序的读取数据源中的数据,而且这些数据是只读的,并不允许作其它的操作。因为DataReader 在读取数据的时候限制了每次只读取一笔,而且只能只读,所以使用起来不但节省资源而且效率很好.
老生常谈的说了一遍ADO.NET 的五个核心对象,这里主要目的是为了更好的了解此篇文章。我想现在用Linq to SQL , Linq to Entity 的人太多了,或许都忘记了ADO.NET 的基本操作,其实我本人也是如此,一段时间不是用好多忘记了,这里再次复习一遍ADO.NET 能更好的理解此篇文章。
3. 数据库加载驱动操作接口
该数据库操作接口很简单,就是封装了一些数据库操作的常用接口和命令,并定义了一些数据库连接和关闭的方法,并控制了数据库事务提交和回滚的方法。不过在这里的方法实现中我并没有对事务进行处理,如果对本文有兴趣的人可以在后期的文章中关注,我会对此进行补充。
下面简单看看数据库加载驱动接口:
2 * 2010-2-2
3 *
4 * 情 缘
5 *
6 * 数据库提供加载驱动接口,该接口继承IDisposable,
7 * 用于释放对象占用的内存。该接口定义了数据库链接
8 * 语句,链接对象,执行命令,适配器模式接口。同时
9 * 还提供了打开数据库连接和关闭的方法,还有三个方
10 * 法是用于控制数据库操作事务
11 *
12 * */
13
14 using System;
15 using System.Collections.Generic;
16 using System.Linq;
17 using System.Text;
18 using System.Data;
19
20 namespace CommonData.Data.Core
21 {
22 public interface IDbProvider:IDisposable
23 {
24 /// <summary>
25 /// 数据库链接语句
26 /// </summary>
27 string ConnectionString { get; set; }
28
29 /// <summary>
30 /// 数据库连接对象
31 /// </summary>
32 IDbConnection Connection { get; set; }
33
34 /// <summary>
35 /// 数据库操作命令
36 /// </summary>
37 IDbCommand Command { get; set; }
38
39 /// <summary>
40 /// 数据库操作适配器
41 /// </summary>
42 IDbDataAdapter Adapter { get; set; }
43
44 /// <summary>
45 /// 打开数据库连接方法
46 /// </summary>
47 void Open();
48
49 /// <summary>
50 /// 关闭数据库连接方法
51 /// </summary>
52 void Close();
53
54 /// <summary>
55 /// 开始事务控制方法
56 /// </summary>
57 void BeginTransaction();
58
59 /// <summary>
60 /// 事务回滚方法
61 /// </summary>
62 void RollBack();
63
64 /// <summary>
65 /// 事务提交方法
66 /// </summary>
67 void Commit();
68 }
69 }
70
这里数据库操作的常用对象都是采用的顶层的接口作为属性。至于为什么使用接口,它的好处已经说的太多了,次数也很多了,这里就不再多说。而public interface IDbProvider:IDisposable 集成这个接口,让程序自动管理对象,释放对象占用内存空间。
简单的看看SQL Server 数据库加载驱动操作类:
2 * 2010-2-2
3 *
4 * 情 缘
5 *
6 * SQL Server 数据库操作基本对象
7 * 该类实现了IDbProvider 接口。
8 *
9 * */
10 using System;
11 using System.Collections.Generic;
12 using System.Linq;
13 using System.Text;
14 using System.Data.SqlClient;
15 using System.Data;
16
17 namespace CommonData.Data.Core.SQLCore
18 {
19 public class SqlProvider : IDbProvider
20 {
21 private string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["DataBaseConfig"].ConnectionString;
22 /// <summary>
23 /// 数据库连接字符串
24 /// </summary>
25 public string ConnectionString
26 {
27 get
28 {
29 if (connectionString == null)
30 {
31 connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["DataBaseConfig"].ConnectionString;
32 }
33 return connectionString;
34 }
35 set
36 {
37 connectionString = value;
38 }
39 }
40
41 private IDbConnection connection = null;
42 /// <summary>
43 /// 数据库连接对象
44 /// </summary>
45 public IDbConnection Connection
46 {
47 get
48 {
49 if (connection == null)
50 {
51 connection = new SqlConnection(connectionString);
52 }
53 return connection;
54 }
55 set
56 {
57 connection = value;
58 }
59 }
60
61 private IDbCommand command = null;
62 /// <summary>
63 /// 数据库命令操作对象
64 /// </summary>
65 public IDbCommand Command
66 {
67 get
68 {
69 if (command == null)
70 {
71 command = new SqlCommand();
72 command.Connection = connection;
73 }
74 return command;
75 }
76 set
77 {
78 command = value;
79 }
80 }
81
82 private IDbDataAdapter adapter = null;
83 /// <summary>
84 /// 数据库适配器对象
85 /// </summary>
86 public IDbDataAdapter Adapter
87 {
88 get
89 {
90 if (adapter == null)
91 {
92 adapter = new SqlDataAdapter(command as SqlCommand);
93 }
94 return adapter;
95 }
96 set
97 {
98 adapter = value;
99 }
100 }
101
102 /// <summary>
103 /// 数据库事务对象
104 /// </summary>
105 private IDbTransaction transaction = null;
106
107 /// <summary>
108 /// 打开数据库连接
109 /// </summary>
110 public void Open()
111 {
112 if (connection != null)
113 {
114 connection.Open();
115 }
116 }
117
118 /// <summary>
119 /// 关闭数据库连接
120 /// </summary>
121 public void Close()
122 {
123 if (connection != null)
124 {
125 connection.Close();
126 }
127 }
128
129 /// <summary>
130 /// 开始事务
131 /// </summary>
132 public void BeginTransaction()
133 {
134 transaction = connection.BeginTransaction();
135 command.Transaction = transaction;
136 }
137
138 /// <summary>
139 /// 事务回滚
140 /// </summary>
141 public void RollBack()
142 {
143 if (transaction != null)
144 {
145 transaction.Rollback();
146 command.Transaction = null;
147 transaction.Dispose();
148 }
149 }
150
151 /// <summary>
152 /// 事务提交
153 /// </summary>
154 public void Commit()
155 {
156 if (transaction != null)
157 {
158 transaction.Commit();
159 command.Transaction = null;
160 transaction.Dispose();
161 }
162 }
163
164 /// <summary>
165 /// 创建数据库加载驱动
166 /// </summary>
167 /// <returns></returns>
168 public IDbProvider CreateInstance()
169 {
170 return new SqlProvider();
171 }
172
173 /// <summary>
174 /// 释放内存空间
175 /// </summary>
176 public void Dispose()
177 {
178 GC.SuppressFinalize(this);
179 }
180 }
181 }
182
对于其他的数据库来说,使用操作的对象和命令都不同,他是它们都提供抽象出来了一个公共接口就是IDbProvider (数据提供加载驱动)。在接口中定义的每个get set 方法都进行了实现实现了一个属性的封装,并且提供了唯一对象的变量。(C#中属性的封装其实也就是一个get,set方法,所以在接口中能够这样定义方法)
4. 数据库的操作命令
ADO.NET 中查询数据库,返回的结果分为多种情况,而数据库的操作无非就四种情况增删改查.
而这四种情况又可以分为两大类:
(1). 数据库的修改操作: 数据的增加,修改,删除都对数据进行了操作,都有写的动作,对数据结构有了变动。
(2). 数据库的查询操作:数据库的查询,也就是读取数据,这个操作不会对数据的数据结构进行修改,因此这里可以单独分为一类。当然一类也就是比较复杂的一类了,查询的情况会很多不同。
下面是数据库操作的接口:
2 * 2010-3-5
3 *
4 * 情 缘
5 *
6 * 该接口定义了数据库操作的各种方法,该接口定义
7 * 工作职责比较明确,只是针对数据的操作,不需要
8 * 管理数据库的连接等过程。此接口还包含了一个数
9 * 据流和集合类型的转换的方法定义
10 *
11 * */
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using System.Text;
16 using System.Data;
17
18 namespace CommonData.Data.Core
19 {
20 public interface IBaseHelper:IDisposable
21 {
22 /// <summary>
23 /// 返回受影响行数
24 /// </summary>
25 /// <param name="provider">数据提供加载驱动</param>
26 /// <param name="sqlString">sql语句</param>
27 /// <returns></returns>
28 int ExecuteNonQuery(IDbProvider provider, string sqlString);
29
30 /// <summary>
31 /// 返回受影响行数
32 /// </summary>
33 /// <param name="provider">数据提供加载驱动</param>
34 /// <param name="sqlString">sql语句</param>
35 /// <param name="isProcedure">是否为存储过程</param>
36 /// <returns></returns>
37 int ExecuteNonQuery(IDbProvider provider, string sqlString, bool isProcedure);
38
39 /// <summary>
40 /// 返回受影响行数
41 /// </summary>
42 /// <param name="provider">数据提供加载驱动</param>
43 /// <param name="sqlString">sql语句</param>
44 /// <param name="param">sql语句对应参数</param>
45 /// <returns></returns>
46 int ExecuteNonQuery(IDbProvider provider, string sqlString, params IDataParameter[] param);
47
48 /// <summary>
49 /// 返回受影响行数
50 /// </summary>
51 /// <param name="provider">数据提供加载驱动</param>
52 /// <param name="sqlString">sql语句</param>
53 /// <param name="isProcedure">是否为存储过程,true 为存储过程</param>
54 /// <param name="param">sql语句对应参数</param>
55 /// <returns></returns>
56 int ExecuteNonQuery(IDbProvider provider, string sqlString, bool isProcedure, params IDataParameter[] param);
57
58 /// <summary>
59 /// 返回查询语句第一行第一列
60 /// </summary>
61 /// <param name="provider">数据提供加载驱动</param>
62 /// <param name="sqlString">sql语句</param>
63 /// <returns></returns>
64 object ExecuteScalar(IDbProvider provider, string sqlString);
65
66 /// <summary>
67 /// 返回查询语句第一行第一列
68 /// </summary>
69 /// <param name="provider">数据提供加载驱动</param>
70 /// <param name="sqlString">sql语句</param>
71 /// <param name="isProcedure">是否是存储过程</param>
72 /// <returns></returns>
73 object ExecuteScalar(IDbProvider provider, string sqlString, bool isProcedure);
74
75 /// <summary>
76 /// 返回查询语句第一行第一列
77 /// </summary>
78 /// <param name="provider">数据提供加载驱动</param>
79 /// <param name="sqlString">sql语句</param>
80 /// <param name="param">sql语句对应输入参数</param>
81 /// <returns></returns>
82 object ExecuteScalar(IDbProvider provider, string sqlString, params IDataParameter[] param);
83
84 /// <summary>
85 /// 返回查询语句第一行第一列
86 /// </summary>
87 /// <param name="provider">数据提供加载驱动</param>
88 /// <param name="sqlString">sql语句</param>
89 /// <param name="isProcedure">是否为存储过程</param>
90 /// <param name="param">sql语句对应输入参数</param>
91 /// <returns></returns>
92 object ExecuteScalar(IDbProvider provider, string sqlString, bool isProcedure, params IDataParameter[] param);
93
94 /// <summary>
95 /// 返回数据只读游标集
96 /// </summary>
97 /// <param name="provider">数据提供加载驱动</param>
98 /// <param name="sqlString">sql语句</param>
99 /// <returns></returns>
100 IDataReader ExecuteDataReader(IDbProvider provider, string sqlString);
101
102 /// <summary>
103 /// 返回数据只读游标集
104 /// </summary>
105 /// <param name="provider">数据提供加载驱动</param>
106 /// <param name="sqlString">sql语句</param>
107 /// <param name="isProcedure">是否为存储过程</param>
108 /// <returns></returns>
109 IDataReader ExecuteDataReader(IDbProvider provider, string sqlString, bool isProcedure);
110
111 /// <summary>
112 /// 返回数据只读游标集
113 /// </summary>
114 /// <param name="provider">数据提供加载驱动</param>
115 /// <param name="sqlString">sql语句</param>
116 /// <param name="param">sql语句对应输入参数</param>
117 /// <returns></returns>
118 IDataReader ExecuteDataReader(IDbProvider provider, string sqlString, params IDataParameter[] param);
119
120 /// <summary>
121 /// 返回数据只读游标集
122 /// </summary>
123 /// <param name="provider">数据提供加载驱动</param>
124 /// <param name="sqlString">sql语句</param>
125 /// <param name="isProcedure">是否为存储过程</param>
126 /// <param name="param">sql语句对应输入参数</param>
127 /// <returns></returns>
128 IDataReader ExecuteDataReader(IDbProvider provider, string sqlString, bool isProcedure, params IDataParameter[] param);
129
130 /// <summary>
131 /// 获得数据表结构集合
132 /// </summary>
133 /// <param name="provider">数据提供加载驱动</param>
134 /// <param name="sqlString">sql语句</param>
135 /// <returns></returns>
136 DataTable ExecuteTable(IDbProvider provider, string sqlString);
137
138 /// <summary>
139 /// 获得数据表结构集合
140 /// </summary>
141 /// <param name="provider">数据提供加载驱动</param>
142 /// <param name="sqlString">sql语句</param>
143 /// <param name="isProcedure">是否为存储过程</param>
144 /// <returns></returns>
145 DataTable ExecuteTable(IDbProvider provider, string sqlString, bool isProcedure);
146
147 /// <summary>
148 /// 获得数据表结构集合
149 /// </summary>
150 /// <param name="provider">数据提供加载驱动</param>
151 /// <param name="sqlString">sql语句</param>
152 /// <param name="param">sql语句对应参数</param>
153 /// <returns></returns>
154 DataTable ExecuteTable(IDbProvider provider, string sqlString, params IDataParameter[] param);
155
156 /// <summary>
157 /// 获得数据表结构集合
158 /// </summary>
159 /// <param name="provider">数据提供加载驱动</param>
160 /// <param name="sqlString">sql语句</param>
161 /// <param name="isProcedure">是否为存储过程</param>
162 /// <param name="param">sql语句对应参数</param>
163 /// <returns></returns>
164 DataTable ExecuteTable(IDbProvider provider, string sqlString, bool isProcedure, params IDataParameter[] param);
165
166
167
168 /// <summary>
169 /// 根据一个泛型类型获得实体对象
170 /// </summary>
171 /// <typeparam name="T">泛型类型</typeparam>
172 /// <param name="reader">只读数据流</param>
173 /// <returns></returns>
174 T ConvertToEntity<T>(IDataReader reader) where T : class ;
175
176 /// <summary>
177 /// 将数据流装化为对象
178 /// </summary>
179 /// <param name="type">转化的目标类型</param>
180 /// <param name="reader">只读数据流</param>
181 /// <returns></returns>
182 object ConvertToEntity(Type type,IDataReader reader);
183
184 /// <summary>
185 /// 根据一个泛型类型查询一个集合
186 /// </summary>
187 /// <typeparam name="T">泛型类型</typeparam>
188 /// <param name="reader">只读数据流</param>
189 /// <returns></returns>
190 IList<T> ConvertToList<T>(IDataReader reader) where T : class;
191 }
192 }
193
a).查询返回受影响的行数
查询返回受影响的行数,主要针对于数据库的增删改三个动作,在这三个动作中都是修改了数据库的结构。而SQL Server是关系型数据库,对于数据库的修改都是以数据行的形式来修改的。所以在对数据库进行结构修改时,返回的都是受影响的数据行数。
SQL Server返回受影响行数方法实现
2 /// 返回受影响行数
3 /// </summary>
4 /// <param name="provider">数据提供加载驱动</param>
5 /// <param name="sqlString">sql语句</param>
6 /// <returns></returns>
7 public int ExecuteNonQuery(IDbProvider provider, string sqlString)
8 {
9 return ExecuteNonQuery(provider, sqlString, false, null);
10 }
11
12 /// <summary>
13 /// 返回受影响行数
14 /// </summary>
15 /// <param name="provider">数据提供加载驱动</param>
16 /// <param name="sqlString">sql语句</param>
17 /// <param name="isProcedure">是否为存储过程</param>
18 /// <returns></returns>
19 public int ExecuteNonQuery(IDbProvider provider, string sqlString, bool isProcedure)
20 {
21 return ExecuteNonQuery(provider, sqlString, isProcedure, null);
22 }
23
24 /// <summary>
25 /// 返回受影响行数
26 /// </summary>
27 /// <param name="provider">数据提供加载驱动</param>
28 /// <param name="sqlString">sql语句</param>
29 /// <param name="param">sql语句对应参数</param>
30 /// <returns></returns>
31 public int ExecuteNonQuery(IDbProvider provider, string sqlString, params IDataParameter[] param)
32 {
33 return ExecuteNonQuery(provider, sqlString, false, param);
34 }
35
36 /// <summary>
37 /// 返回受影响行数
38 /// </summary>
39 /// <param name="provider">数据提供加载驱动</param>
40 /// <param name="sqlString">sql语句</param>
41 /// <param name="isProcedure">是否为存储过程,true 为存储过程</param>
42 /// <param name="param">sql语句对应参数</param>
43 /// <returns></returns>
44 public int ExecuteNonQuery(IDbProvider provider, string sqlString, bool isProcedure, params IDataParameter[] param)
45 {
46 provider.Connection.Open();
47 provider.Command.CommandText = sqlString;
48 if (isProcedure)
49 {
50 provider.Command.CommandType = CommandType.StoredProcedure;
51 }
52 else
53 {
54 provider.Command.CommandType = CommandType.Text;
55 }
56 provider.Command.Parameters.Clear();
57 provider.Command.Parameters.AddRange(param);
58 int line = (int)provider.Command.ExecuteNonQuery();
59 return line;
60 }
从上面的源码可以看出,其实最终所有的方法都指向了一个方法,而这个方法有个特殊的地方就是bool isProcedure,用此参数可以判断这个操作的是SQL 语句还是存储过程。在这个方法中还使用到了一个特殊的参数provider.Command.Parameters,而Parameters集合是没有AddRange()方法的(而SqlParameters有这个方法),这个方法是使用的一个扩展方法,在.NET3.0 开始扩展方法为.NET 平台注入了新鲜的血液。让.NET 平台变的如此有魅力。
b).查询返回数据集的第一行第一列
查询结果返回第一行第一列,我们用得最多的也就是聚合函数的使用了,聚合函数查询一般也就是查询返回一个结果。这里也就不再多讲解,看看方法实现的代码
2 /// 返回查询语句第一行第一列
3 /// </summary>
4 /// <param name="provider">数据提供加载驱动</param>
5 /// <param name="sqlString">sql语句</param>
6 /// <returns></returns>
7 public object ExecuteScalar(IDbProvider provider, string sqlString)
8 {
9 return ExecuteScalar(provider, sqlString, false, null);
10 }
11
12 /// <summary>
13 /// 返回查询语句第一行第一列
14 /// </summary>
15 /// <param name="provider">数据提供加载驱动</param>
16 /// <param name="sqlString">sql语句</param>
17 /// <param name="isProcedure">是否是存储过程</param>
18 /// <returns></returns>
19 public object ExecuteScalar(IDbProvider provider, string sqlString, bool isProcedure)
20 {
21 return ExecuteScalar(provider, sqlString, isProcedure, null);
22 }
23
24 /// <summary>
25 /// 返回查询语句第一行第一列
26 /// </summary>
27 /// <param name="provider">数据提供加载驱动</param>
28 /// <param name="sqlString">sql语句</param>
29 /// <param name="param">sql语句对应输入参数</param>
30 /// <returns></returns>
31 public object ExecuteScalar(IDbProvider provider, string sqlString, params IDataParameter[] param)
32 {
33 return ExecuteScalar(provider, sqlString, false, param);
34 }
35
36 /// <summary>
37 /// 返回查询语句第一行第一列
38 /// </summary>
39 /// <param name="provider">数据提供加载驱动</param>
40 /// <param name="sqlString">sql语句</param>
41 /// <param name="isProcedure">是否为存储过程</param>
42 /// <param name="param">sql语句对应输入参数</param>
43 /// <returns></returns>
44 public object ExecuteScalar(IDbProvider provider, string sqlString, bool isProcedure, params IDataParameter[] param)
45 {
46 provider.Connection.Open();
47 provider.Command.CommandText = sqlString;
48 if (isProcedure)
49 {
50 provider.Command.CommandType = CommandType.StoredProcedure;
51 }
52 else
53 {
54 provider.Command.CommandType = CommandType.Text;
55 }
56 provider.Command.Parameters.Clear();
57 provider.Command.Parameters.AddRange(param);
58 object result = provider.Command.ExecuteScalar();
59 return result;
60 }
c).查询返回只读数据流
查询只读数据流,返回的就是IDataReader,在ADO.NET 中查询返回只读数据流,是一种特别高效的读取数据的方式。作为.NET程序员我们一般都是使用的SqlDataReader 这个类,其实在程序架构的时候使用其父类接口IdataReader,程序更具灵活性,而这里的IdataReader 其实还有一个更重要的作用。那就是返回结果集合的时候,比如Ilist<T>。对于返回List<T> 结果在后面做介绍。
返回IdataReader 源码
2 /// 返回数据只读游标集
3 /// </summary>
4 /// <param name="provider">数据提供加载驱动</param>
5 /// <param name="sqlString">sql语句</param>
6 /// <returns></returns>
7 public IDataReader ExecuteDataReader(IDbProvider provider, string sqlString)
8 {
9 return ExecuteDataReader(provider, sqlString, false, null);
10 }
11
12 /// <summary>
13 /// 返回数据只读游标集
14 /// </summary>
15 /// <param name="provider">数据提供加载驱动</param>
16 /// <param name="sqlString">sql语句</param>
17 /// <param name="isProcedure">是否为存储过程</param>
18 /// <returns></returns>
19 public IDataReader ExecuteDataReader(IDbProvider provider, string sqlString, bool isProcedure)
20 {
21 return ExecuteDataReader(provider, sqlString, isProcedure, null);
22 }
23
24 /// <summary>
25 /// 返回数据只读游标集
26 /// </summary>
27 /// <param name="provider">数据提供加载驱动</param>
28 /// <param name="sqlString">sql语句</param>
29 /// <param name="param">sql语句对应输入参数</param>
30 /// <returns></returns>
31 public IDataReader ExecuteDataReader(IDbProvider provider, string sqlString, params IDataParameter[] param)
32 {
33 return ExecuteDataReader(provider, sqlString, false, param);
34 }
35
36 /// <summary>
37 /// 返回数据只读游标集
38 /// </summary>
39 /// <param name="provider">数据提供加载驱动</param>
40 /// <param name="sqlString">sql语句</param>
41 /// <param name="isProcedure">是否为存储过程</param>
42 /// <param name="param">sql语句对应输入参数</param>
43 /// <returns></returns>
44 public IDataReader ExecuteDataReader(IDbProvider provider, string sqlString, bool isProcedure, params IDataParameter[] param)
45 {
46 provider.Connection.Open();
47 provider.Command.CommandText = sqlString;
48 if (isProcedure)
49 {
50 provider.Command.CommandType = CommandType.StoredProcedure;
51 }
52 else
53 {
54 provider.Command.CommandType = CommandType.Text;
55 }
56 provider.Command.Parameters.Clear();
57 provider.Command.Parameters.AddRange(param);
58 IDataReader reader = provider.Command.ExecuteReader();
59 return reader;
60 }
d).查询返回DataTable
DataTable 相当于内存中小型数据库的表,查询的数据库结果将以表的结构保存在内存中,这个是ADO.NET中断开式数据库链接操作数据的一种有效方式。对于这种方式,查询数据还是比较方便的,但是对于数据库的增删改用DataTable 就比较麻烦了,可以查看ADO.NET数据库操作的具体内容,这里不做多的介绍。
查询返回DataTable 结果集源码
2 /// 获得数据表结构集合
3 /// </summary>
4 /// <param name="provider">数据提供加载驱动</param>
5 /// <param name="sqlString">sql语句</param>
6 /// <returns></returns>
7 public DataTable ExecuteTable(IDbProvider provider, string sqlString)
8 {
9 return ExecuteTable(provider, sqlString, false, null);
10 }
11
12 /// <summary>
13 /// 获得数据表结构集合
14 /// </summary>
15 /// <param name="provider">数据提供加载驱动</param>
16 /// <param name="sqlString">sql语句</param>
17 /// <param name="isProcedure">是否为存储过程</param>
18 /// <returns></returns>
19 public DataTable ExecuteTable(IDbProvider provider, string sqlString, bool isProcedure)
20 {
21 return ExecuteTable(provider, sqlString, isProcedure, null);
22 }
23
24 /// <summary>
25 /// 获得数据表结构集合
26 /// </summary>
27 /// <param name="provider">数据提供加载驱动</param>
28 /// <param name="sqlString">sql语句</param>
29 /// <param name="param">sql语句对应参数</param>
30 /// <returns></returns>
31 public DataTable ExecuteTable(IDbProvider provider, string sqlString, params IDataParameter[] param)
32 {
33 return ExecuteTable(provider, sqlString, false, param);
34 }
35
36 /// <summary>
37 /// 获得数据表结构集合
38 /// </summary>
39 /// <param name="provider">数据提供加载驱动</param>
40 /// <param name="sqlString">sql语句</param>
41 /// <param name="isProcedure">是否为存储过程</param>
42 /// <param name="param">sql语句对应参数</param>
43 /// <returns></returns>
44 public DataTable ExecuteTable(IDbProvider provider, string sqlString, bool isProcedure, params IDataParameter[] param)
45 {
46 provider.Connection.Open();
47 provider.Command.CommandText = sqlString;
48 if (isProcedure)
49 {
50 provider.Command.CommandType = CommandType.StoredProcedure;
51 }
52 else
53 {
54 provider.Command.CommandType = CommandType.Text;
55 }
56 provider.Command.Parameters.Clear();
57 provider.Command.Parameters.AddRange(param);
58 DataSet ds = new DataSet();
59 provider.Adapter.Fill(ds);
60 return ds.Tables[0];
61 }
5. IdataReader 转换集合
上面提到了,这个ORM映射框架可以查询返回Ilist<T>,程序开发过程中我们往往喜欢使用List 结合,特别是泛型集合。上面的数据库操作其中一种返回的是IdataReader,于是我们就想使用IdataReader 转换为List集合,或者List<T>泛型集合。但是这里遇到了一个问题,如果转换为List<T> 泛型集合,我们如果给泛型类型赋值,在这个数据库的操作过程中是进行了高度的抽象的,我们是无法知道操作的具体类型,因此我们想到的是使用反射机制,在前面提到过的实体分析器,我们使用实体分析器分析了实体的详细信息,并缓存在内存中。因此我们有了这个信息就可以很好的和数据库对应起来。这个转换的核心工作就是反射赋值,下面看看实现方式:
IdataReader 转换为 T 泛型实体类:
2 /// 根据一个泛型类型获得实体对象
3 /// </summary>
4 /// <typeparam name="T">泛型类型</typeparam>
5 /// <param name="reader">只读数据流</param>
6 /// <returns></returns>
7 public T ConvertToEntity<T>(IDataReader reader) where T:class
8 {
9 T entity = default(T);
10 object result=ConvertToEntity(typeof(T),reader);
11 if (result != null)
12 {
13 entity=(T)result;
14 }
15 return entity;
16 }
17
18 /// <summary>
19 /// 将数据流装化为对象
20 /// </summary>
21 /// <param name="type">转化的目标类型</param>
22 /// <param name="reader">只读数据流</param>
23 /// <returns></returns>
24 public object ConvertToEntity(Type type, IDataReader reader)
25 {
26 object entity = null;
27 if (reader.Read())
28 {
29 entity = EntityFactory.CreateInstance(type);
30 foreach (string key in EntityTypeCache.GetTableInfo(type).DicColumns.Keys)
31 {
32 if (string.IsNullOrEmpty(reader[key].ToString()))
33 {
34 EntityTypeCache.GetTableInfo(type).DicProperties[key].SetValue(entity, "", null);
35 }
36 else
37 {
38 EntityTypeCache.GetTableInfo(type).DicProperties[key].SetValue(entity, reader[key], null);
39 }
40 }
41 if (EntityTypeCache.GetTableInfo(type).DicLinkTable.Keys.Count > 0)
42 {
43 foreach (string key in EntityTypeCache.GetTableInfo(type).DicLinkTable.Keys)
44 {
45 Type entityType = EntityTypeCache.GetTableInfo(type).DicLinkTable[key].DataType;
46 string sql = Factory.CreateSingleSql(entityType);
47 IDataParameter[] param = new IDataParameter[]{
48 new SqlParameter()
49 };
50 param[0].ParameterName = "@" + EntityTypeCache.GetTableInfo(EntityTypeCache.GetTableInfo(type).DicLinkTable[key].DataType).Table.PrimaryKeyName;
51 param[0].Value = EntityFactory.GetPropertyValue(entity, EntityTypeCache.GetTableInfo(type).DicLinkTable[key].KeyName);
52 using (IDbProvider provider = new SqlProvider())
53 {
54 IDataReader read = ExecuteDataReader(provider, sql, param);
55 object entityChild = EntityFactory.CreateInstance(entityType, false);
56 if (read.Read())
57 {
58 foreach (string propertyName in EntityTypeCache.GetTableInfo(entityType).DicProperties.Keys)
59 {
60 EntityTypeCache.GetTableInfo(entityType).DicProperties[propertyName].SetValue(entityChild, read[EntityTypeCache.GetTableInfo(entityType).DicColumns[propertyName].Name], null);
61 }
62 }
63 EntityTypeCache.GetTableInfo(type).DicProperties[key].SetValue(entity, entityChild, null);
64 }
65 }
66 }
67 }
68 return entity;
69 }
IdataReader 转换为Ilist<T> 泛型集合:
2 /// 根据一个泛型类型查询一个集合
3 /// </summary>
4 /// <typeparam name="T">泛型类型</typeparam>
5 /// <param name="reader">只读数据流</param>
6 /// <returns></returns>
7 public IList<T> ConvertToList<T>(IDataReader reader) where T : class
8 {
9 T entity = default(T);
10 IList<T> list = new List<T>();
11 while (reader.Read())
12 {
13 entity = EntityFactory.CreateInstance<T>();
14
15 foreach (string key in EntityTypeCache.GetTableInfo(typeof(T)).DicColumns.Keys)
16 {
17 if (string.IsNullOrEmpty(reader[key].ToString()))
18 {
19 EntityTypeCache.GetTableInfo(typeof(T)).DicProperties[key].SetValue(entity, null, null);
20 }
21 else
22 {
23 EntityTypeCache.GetTableInfo(typeof(T)).DicProperties[key].SetValue(entity, reader[key], null);
24 }
25 }
26 if (EntityTypeCache.GetTableInfo(typeof(T)).DicLinkTable.Keys.Count > 0)
27 {
28 foreach (string key in EntityTypeCache.GetTableInfo(typeof(T)).DicLinkTable.Keys)
29 {
30 Type entityType = EntityTypeCache.GetTableInfo(typeof(T)).DicLinkTable[key].DataType;
31 string sql = Factory.CreateSingleSql(entityType);
32 IDataParameter[] param = new IDataParameter[]{
33 new SqlParameter()
34 };
35 param[0].ParameterName = "@" + EntityTypeCache.GetTableInfo(EntityTypeCache.GetTableInfo(typeof(T)).DicLinkTable[key].DataType).Table.PrimaryKeyName;
36 param[0].Value = EntityFactory.GetPropertyValue(entity, EntityTypeCache.GetTableInfo(typeof(T)).DicLinkTable[key].KeyName);
37 using (IDbProvider provider = new SqlProvider())
38 {
39 IDataReader read = ExecuteDataReader(provider, sql, param);
40 object entityChild = EntityFactory.CreateInstance(entityType, false);
41 if (read.Read())
42 {
43 foreach (string propertyName in EntityTypeCache.GetTableInfo(entityType).DicProperties.Keys)
44 {
45 EntityTypeCache.GetTableInfo(entityType).DicProperties[propertyName].SetValue(entityChild, read[EntityTypeCache.GetTableInfo(entityType).DicColumns[propertyName].Name], null);
46 }
47 }
48 EntityTypeCache.GetTableInfo(typeof(T)).DicProperties[key].SetValue(entity, entityChild, null);
49 }
50 }
51 }
52 list.Add(entity);
53 }
54 return list;
55 }
对于T 和 Ilist<T> 的转换其实是一样的过程。在这个转换的过程中有几个值得注意的地方。
T entity = default(T);
default(T) 就好像我们实体对象赋初始值一样,在泛型中因为类型的不确定,所以语法规定了以这种方式赋初始值。
entity = EntityFactory.CreateInstance<T>(); 而这据代码是根据泛型类型创建了一个泛型实例,并在内存中分配空间。在这个里面定义了一个类,里面有很多方法,根据不同的情况,在动态创建对象,下面看看这个类的源码,感觉在对象抽象到一定程序的时候,这种动态创建对象的方式就非常有必要了。
2 * 2010-1-28
3 *
4 * 情 缘
5 *
6 * 该实体类主要是通过反射机制来获取泛型实体类的实例的
7 *
8 *
9 * */
10
11 using System;
12 using System.Reflection;
13
14
15 namespace CommonData.Entity
16 {
17 public static class EntityFactory
18 {
19 /// <summary>
20 /// 根据泛型类获取该泛型类的实例,
21 /// T 泛型必须是class 类
22 /// </summary>
23 /// <typeparam name="T">泛型类</typeparam>
24 /// <returns></returns>
25 public static T CreateInstance<T>() where T :class
26 {
27 Type type = typeof(T);
28 Object result;
29 result = Activator.CreateInstance<T>();
30 return (T)result;
31 }
32
33 /// <summary>
34 /// 根据实体类型来创建实体实例
35 /// </summary>
36 /// <param name="type">要创建的对象的类型</param>
37 /// <param name="nonPublic">如果有显示构造方法为true,如果没有显示构造方法为false</param>
38 /// <returns></returns>
39 public static object CreateInstance(Type type,bool nonPublic)
40 {
41 return Activator.CreateInstance(type,nonPublic);
42 }
43
44 /// <summary>
45 /// 根据实体类型和相关参数构造实体实例
46 /// </summary>
47 /// <param name="type">要创建的对象的类型</param>
48 /// <param name="param">与要调用构造函数的参数数量、顺序和类型匹配的参数数组。如果 param 为空数组,则调用不带任何参数的构造函数</param>
49 /// <returns></returns>
50 public static object CreateInstance(Type type,params object[] param)
51 {
52 return Activator.CreateInstance(type,param);
53 }
54
55 /// <summary>
56 /// 根据实体公共接口获得特定属性名称的值
57 /// </summary>
58 /// <param name="entity">实体公共接口</param>
59 /// <param name="name">实体属性名称</param>
60 /// <returns></returns>
61 public static object GetPropertyValue(IEntity entity, string name)
62 {
63 PropertyInfo property = entity.GetType().GetProperty(name);
64 object result = null;
65 if (property != null)
66 {
67 result = property.GetValue(entity, null);
68 }
69 return result;
70 }
71
72 /// <summary>
73 /// 根据实体公共接口获得特定属性名称的值,这个属性是一个类
74 /// </summary>
75 /// <typeparam name="T">返回属性的泛型类型</typeparam>
76 /// <param name="entity">实体公共接口</param>
77 /// <param name="name">实体属性名称</param>
78 /// <returns></returns>
79 public static T GetPropertyValue<T>(IEntity entity, string name) where T:class
80 {
81 object result = GetPropertyValue(entity, name);
82 if (result == null)
83 {
84 return default(T);
85 }
86 else
87 {
88 return (T)result;
89 }
90 }
91
92 /// <summary>
93 /// 获得实体属性值
94 /// </summary>
95 /// <param name="entity">实体类</param>
96 /// <param name="name">属性名称</param>
97 /// <returns></returns>
98 public static object GetPropertyValue(object entity, string name)
99 {
100 PropertyInfo property = entity.GetType().GetProperty(name);
101 object result = null;
102 if (property != null)
103 {
104 result = property.GetValue(entity, null);
105 }
106 return result;
107 }
108
109 /// <summary>
110 /// 根据实体公共接口设置某属性的值
111 /// </summary>
112 /// <param name="entity">实体公共接口</param>
113 /// <param name="name">实体属性名称</param>
114 /// <param name="value">实体属性值</param>
115 public static void SetPropertyValue(IEntity entity, string name, object value)
116 {
117 PropertyInfo property = entity.GetType().GetProperty(name);
118 if (property != null)
119 {
120 property.SetValue(name,value,null);
121 }
122 }
123
124 /// <summary>
125 /// 将某个值转化为特定的类型
126 /// </summary>
127 /// <param name="type">转化为的目标类型</param>
128 /// <param name="value">被转化的值</param>
129 /// <returns></returns>
130 public static object ConvertValue(Type type, object value)
131 {
132 if (value == DBNull.Value)
133 {
134 return null;
135 }
136 return Convert.ChangeType(value,type);
137 }
138
139 /// <summary>
140 /// 将某个值转化为特定的泛型类型
141 /// </summary>
142 /// <typeparam name="T">泛型类型</typeparam>
143 /// <param name="type">转化为的目标类型</param>
144 /// <param name="value">被转化的值</param>
145 /// <returns></returns>
146 public static T ConvertValue<T>(Type type, object value)
147 {
148 if (value == DBNull.Value)
149 {
150 return default(T);
151 }
152 return (T)Convert.ChangeType(value, type);
153 }
154 }
155 }
156
封装集合其实就是根据实体分析缓存的信息,查找对应的数据流中的数据,动态的给对象赋值。在这个动态赋值的过程中有个地方,特别应该注意:
if (string.IsNullOrEmpty(reader[key].ToString()))
这句话就是讲读取的数据转换为字符串,在之前也提到过,.NET 中的数据类型和SQL Server 中的数据类型是不同的,如果reader[key] 的值为null,如果我上面的这句判断改为
If(reader[key]==null) 那么这里就会存在一个潜在的bug,上面已经说过了,数据库中的类型和.NET 中的类型是不一样的,需要使用DbNull 这个对象。更多类容不再多少,可以到网上查看更多的资料。
这个里面还有一个特殊的过程,那就是级联查询,当然这里只是做了级联查询父类的操作,至于级联查询子类集合的过程没有做处理,这个在后期的改版中做修改。
6. 下面举个小小的应用例子
没时间了,简单的介绍一下吧,不做详细的讲解了,后续在讲解。
在这个ORM框架中还定义了一个接口,源码如下:
2 * 2010-2-26
3 *
4 * 情 缘
5 *
6 * 该接口定了实体增删改查的操作。
7 * 接口中的定义都是使用实体的公共
8 * 接口和泛型类型,这样确保了方法
9 * 的公用性
10 *
11 * */
12 using System;
13 using System.Collections.Generic;
14 using System.Linq;
15 using System.Text;
16 using CommonData.Entity;
17 using CommonData.Model.Core;
18
19 namespace CommonData.Data.Core
20 {
21 public interface IDbHelper:IDisposable
22 {
23 /// <summary>
24 /// 添加实体对象
25 /// 将实体数据信息映射为一条插入sql语句
26 /// </summary>
27 /// <param name="entity">实体公共接口</param>
28 /// <returns></returns>
29 int Add(IEntity entity);
30
31 /// <summary>
32 /// 添加实体对象
33 /// 将泛型数据信息映射为一条插入sql语句
34 /// 该泛型类必须实现IEntity 接口
35 /// </summary>
36 /// <typeparam name="T">实体泛型类型</typeparam>
37 /// <param name="t">泛型实体值</param>
38 /// <returns></returns>
39 int Add<T>(T t) where T : IEntity;
40
41 /// <summary>
42 /// 添加实体对象
43 /// value 的类型必须和type一致,这样才能保存值
44 /// </summary>
45 /// <param name="type">实体类型</param>
46 /// <param name="value">实体类型实例</param>
47 /// <returns></returns>
48 int Add(Type type, object value);
49
50 /// <summary>
51 /// 根据实体公共接口修改该实体信息
52 /// 该实体是根据主键修改
53 /// </summary>
54 /// <param name="entity">实体公共接口</param>
55 /// <returns></returns>
56 int Update(IEntity entity);
57
58 /// <summary>
59 /// 根据实体的某个属性修改数据
60 /// entity 中必须包含该属性,而且该属性的
61 /// 值不能为空
62 /// </summary>
63 /// <param name="entity">实体公共接口</param>
64 /// <param name="propertyName">实体属性名称</param>
65 /// <returns></returns>
66 int Update(IEntity entity,string propertyName);
67
68 /// <summary>
69 /// 根据实体的多个属性修改数据
70 /// 数组中的属性名称必须存在.
71 /// 传递参数数组不能为null
72 /// </summary>
73 /// <param name="entity">实体公共接口</param>
74 /// <param name="propertyNames">属性名称数组</param>
75 /// <returns></returns>
76 int Update(IEntity entity,string[] propertyNames);
77
78 /// <summary>
79 /// 修改实体信息
80 /// 该实体是根据主键修改
81 /// </summary>
82 /// <typeparam name="T">实体泛型类型</typeparam>
83 /// <param name="t">泛型实例</param>
84 /// <returns></returns>
85 int Update<T>(T t) where T : IEntity;
86
87 /// <summary>
88 /// 根据泛型类的某个实体属性来修改该数据。
89 /// 泛型实体实例中该属性不能为空
90 /// </summary>
91 /// <typeparam name="T">泛型类</typeparam>
92 /// <param name="t">泛型实例</param>
93 /// <param name="propertyName"></param>
94 /// <returns></returns>
95 int Update<T>(T t, string propertyName) where T : IEntity;
96
97 /// <summary>
98 /// 根据实体的多个属性修改数据
99 /// 数组中的属性名称在泛型类中必须存在,
100 /// 数组不能传递null值
101 /// </summary>
102 /// <typeparam name="T">泛型类</typeparam>
103 /// <param name="t">泛型实例</param>
104 /// <param name="propertyNames">属性名称数组</param>
105 /// <returns></returns>
106 int Update<T>(T t, string[] propertyNames) where T : IEntity;
107
108 /// <summary>
109 /// 修改实体信息
110 /// 该实体是根据主键修改
111 /// </summary>
112 /// <param name="type">实体类型</param>
113 /// <param name="value">实体对象实例</param>
114 /// <returns></returns>
115 int Update(Type type, object value);
116
117 /// <summary>
118 /// 根据实体的某个属性来修改数据信息
119 /// 该方法使用Type 来确定需要修改的实体对象
120 /// value 实例中必须包含propertyName 这个属性
121 /// 而且propertyName 属性值不能为空
122 /// </summary>
123 /// <param name="type">实体类型</param>
124 /// <param name="value">实体实例</param>
125 /// <param name="propertyName">属性名称</param>
126 /// <returns></returns>
127 int Update(Type type, object value, string propertyName);
128
129 /// <summary>
130 /// 根据实体的多个属性来修改数据信息
131 /// 该方法使用Type 来确定需要修改的实体对象
132 /// 数组中的属性名称在泛型类中必须存在,
133 /// 而且数组传递参数不能为null
134 /// </summary>
135 /// <param name="type">实体类型</param>
136 /// <param name="value">实体实例</param>
137 /// <param name="propertyNames">属性名称数组</param>
138 /// <returns></returns>
139 int Update(Type type,object value,string[] propertyNames);
140
141 /// <summary>
142 /// 删除实体对象
143 /// 该方法是根据实体对象主键删除数据
144 /// </summary>
145 /// <param name="entity">实体公共接口</param>
146 /// <returns></returns>
147 int Delete(IEntity entity);
148
149 /// <summary>
150 /// 根据某个实体属性删除数据
151 /// 该实体必须包含指定的属性名称
152 /// 而且实体属性值不能为空
153 /// </summary>
154 /// <param name="entity">实体属性公共接口</param>
155 /// <param name="propertyName">实体属性名称</param>
156 /// <returns></returns>
157 int Delete(IEntity entity, string propertyName);
158
159 /// <summary>
160 /// 根据实体多个属性删除数据
161 /// 实体中必须包含该属性
162 /// 传递参数数组不能为空
163 /// </summary>
164 /// <param name="entity">实体属性公共接口</param>
165 /// <param name="propertyNames">实体属性名称数组</param>
166 /// <returns></returns>
167 int Delete(IEntity entity,string[] propertyNames);
168
169 /// <summary>
170 /// 根据泛型类删除数据
171 /// 该方法是根据实体的主键删除的
172 /// </summary>
173 /// <typeparam name="T">泛型类</typeparam>
174 /// <param name="t">泛型实例</param>
175 /// <returns></returns>
176 int Delete<T>(T t) where T : class;
177
178 /// <summary>
179 /// 根据泛型类的某个属性删除数据
180 /// 泛型类中必须存在该属性,而且
181 /// 属性值不能为空
182 /// </summary>
183 /// <typeparam name="T">泛型类型</typeparam>
184 /// <param name="t">泛型类实例</param>
185 /// <param name="propertyName">属性名称</param>
186 /// <returns></returns>
187 int Delete<T>(T t, string propertyName) where T : class;
188
189 /// <summary>
190 /// 根据泛型类型的多个属性删除数据
191 /// 泛型类型中必须存在这些属性,传
192 /// 递参数的时候不能为null
193 /// </summary>
194 /// <typeparam name="T">泛型类</typeparam>
195 /// <param name="t">泛型实例</param>
196 /// <param name="propertyNames">属性名称数组</param>
197 /// <returns></returns>
198 int Delete<T>(T t, string[] propertyNames) where T : class;
199
200 /// <summary>
201 /// 根据实体的类型删除数据。
202 /// value 中的类型由type确定
203 /// </summary>
204 /// <param name="type">实体类型</param>
205 /// <param name="value">实体对象实例</param>
206 /// <returns></returns>
207 int Delete(Type type, object value);
208
209 /// <summary>
210 /// 根据实体的类型的某个属性删除数据。
211 /// value 中的类型由type确定
212 /// propertyName 属性名称必须在value
213 /// 对象中存在
214 /// </summary>
215 /// <param name="type">实体类型</param>
216 /// <param name="value">实体对象实例</param>
217 /// <param name="propertyName">属性名称</param>
218 /// <returns></returns>
219 int Delete(Type type,object value,string propertyName);
220
221 /// <summary>
222 /// 根据实体的类型的某个属性删除数据。
223 /// value 中的类型由type确定
224 /// propertyName 属性名称必须在value
225 /// 对象中存在
226 /// </summary>
227 /// <param name="type">实体类型</param>
228 /// <param name="value">实体对象实例</param>
229 /// <param name="propertyNames">属性名称数组</param>
230 /// <returns></returns>
231 int Delete(Type type,object value,string[] propertyNames);
232
233 /// <summary>
234 /// 根据主键查询实体对象
235 /// </summary>
236 /// <typeparam name="T">泛型类型</typeparam>
237 /// <param name="pkPropertyValue">主键值</param>
238 /// <returns></returns>
239 T GetEntity<T>(object pkPropertyValue) where T : class;
240
241 /// <summary>
242 /// 根据实体类的类型和主键值查询实体对象
243 /// 使用 type 确定实体,主键确定数据的唯
244 /// 一性
245 /// </summary>
246 /// <param name="type">实体类型</param>
247 /// <param name="pkPropertyValue">主键值</param>
248 /// <returns></returns>
249 object GetEntity(Type type, object pkPropertyValue);
250
251 /// <summary>
252 /// 根据某个实体的属性来查询实体对象
253 /// 该属性值能确定数据库唯一数据行
254 /// </summary>
255 /// <typeparam name="T">实体泛型类</typeparam>
256 /// <param name="propertyName">属性名称</param>
257 /// <param name="propertyValue">属性值</param>
258 /// <returns></returns>
259 T GetEntity<T>(string propertyName, object propertyValue) where T : class;
260
261 /// <summary>
262 /// 根据某个实体的属性来查询实体对象
263 /// 该属性值能确定数据库唯一数据行
264 /// </summary>
265 /// <param name="type">实体类型</param>
266 /// <param name="propertyName">属性名称</param>
267 /// <param name="propertyValue">属性值</param>
268 /// <returns></returns>
269 object GetEntity(Type type, string propertyName, object propertyValue);
270
271 /// <summary>
272 /// 根据某个实体的多个属性来查询实体对象
273 /// </summary>
274 /// <typeparam name="T">泛型类</typeparam>
275 /// <param name="entity">实体公共接口</param>
276 /// <param name="propertyNames">属性名称数组</param>
277 /// <returns></returns>
278 T GetEntity<T>(IEntity entity, string[] propertyNames) where T : class;
279
280 /// <summary>
281 /// 根据某个实体的多个属性来查询实体对象
282 /// 实体根据type类型来确定
283 /// </summary>
284 /// <param name="type">实体类型</param>
285 /// <param name="entity">实体公共接口</param>
286 /// <param name="propertyNames">属性名称数组</param>
287 /// <returns></returns>
288 object GetEntity(Type type, IEntity entity, string[] propertyNames);
289
290 /// <summary>
291 /// 查询该类型实体数据行数
292 /// </summary>
293 /// <param name="type">实体类型</param>
294 /// <returns></returns>
295 int GetCount(Type type);
296
297 /// <summary>
298 /// 查询该类型实体数据行数
299 /// </summary>
300 /// <typeparam name="T">泛型类型</typeparam>
301 /// <returns></returns>
302 int GetCount<T>() where T : class;
303
304 /// <summary>
305 /// 根据条件查询实体数据行数
306 /// </summary>
307 /// <param name="type">实体类型</param>
308 /// <param name="dic">实体属性键值对</param>
309 /// <param name="component">查询组件</param>
310 /// <returns></returns>
311 int GetCount(Type type, IDictionary<string, object> dic, ConditionComponent component);
312
313 /// <summary>
314 /// 查询所有实体集合
315 /// </summary>
316 /// <typeparam name="T">泛型类型</typeparam>
317 /// <returns></returns>
318 IList<T> GetList<T>() where T : class;
319
320 /// <summary>
321 /// 根据某个实体属性查询实体集合
322 /// </summary>
323 /// <typeparam name="T">泛型类型</typeparam>
324 /// <param name="propertyName">属性名称</param>
325 /// <param name="value">属性值</param>
326 /// <returns></returns>
327 IList<T> GetList<T>(string propertyName, object value) where T : class;
328
329 /// <summary>
330 /// 根据多个属性查询实体集合
331 /// </summary>
332 /// <typeparam name="T">泛型类型</typeparam>
333 /// <param name="entity">实体公共接口</param>
334 /// <param name="propertyNames">属性名称</param>
335 /// <returns></returns>
336 IList<T> GetList<T>(IDictionary<string, object> dic) where T : class;
337
338 /// <summary>
339 /// 根据多个属性查询实体集合
340 /// 该查询方式附加查询组建
341 /// </summary>
342 /// <typeparam name="T">类型类</typeparam>
343 /// <param name="dic">属性键值对</param>
344 /// <param name="component">查询组件</param>
345 /// <returns></returns>
346 IList<T> GetList<T>(IDictionary<string, object> dic, ConditionComponent component) where T : class;
347 }
348 }
349
上面的接口实现类:
2 * 2010-2-26
3 *
4 * 情 缘
5 *
6 * 当前类实现了IDbHelper接口,主要用于对实体进行
7 * 增删改查操作。
8 *
9 * */
10 using System;
11 using System.Collections.Generic;
12 using System.Linq;
13 using System.Text;
14 using CommonData.Entity;
15 using System.Data;
16 using CommonData.Model.Core;
17
18 namespace CommonData.Data.Core.SQLCore
19 {
20 public class SqlHelper:IDbHelper
21 {
22 private IBaseHelper baseHelper;
23 /// <summary>
24 /// 数据库操作公共接口
25 /// </summary>
26 public IBaseHelper BaseHelper
27 {
28 get
29 {
30 if (baseHelper == null)
31 {
32 baseHelper = new BaseHelper();
33 }
34 return baseHelper;
35 }
36 set
37 {
38 baseHelper = value;
39 }
40 }
41
42 private IDbFactory factory;
43 /// <summary>
44 /// sql语句构造工厂对象
45 /// </summary>
46 public IDbFactory Factory
47 {
48 get
49 {
50 if (factory == null)
51 {
52 factory = new SqlFactory();
53 }
54 return factory;
55 }
56 set
57 {
58 factory = value;
59 }
60 }
61
62
63 /// <summary>
64 /// 添加实体对象
65 /// 将实体数据信息映射为一条插入sql语句
66 /// </summary>
67 /// <param name="entity">实体公共接口</param>
68 /// <returns></returns>
69 public int Add(IEntity entity)
70 {
71 IDataParameter[] param = null;
72 string sql = Factory.CreateInsertSql(entity,out param);
73 using(IDbProvider provider=new SqlProvider())
74 {
75 return BaseHelper.ExecuteNonQuery(provider,sql,param);
76 }
77 }
78
79 /// <summary>
80 /// 添加实体对象
81 /// 将泛型数据信息映射为一条插入sql语句
82 /// 该泛型类必须实现IEntity 接口
83 /// </summary>
84 /// <typeparam name="T">实体泛型类型</typeparam>
85 /// <param name="t">泛型实体值</param>
86 /// <returns></returns>
87 public int Add<T>(T t) where T : IEntity
88 {
89 IDataParameter[] param = null;
90 string sql = Factory.CreateInsertSql<T>(t,out param);
91 using (IDbProvider provider = new SqlProvider())
92 {
93 return BaseHelper.ExecuteNonQuery(provider, sql, param);
94 }
95 }
96
97 /// <summary>
98 /// 添加实体对象
99 /// value 的类型必须和type一致,这样才能保存值
100 /// </summary>
101 /// <param name="type">实体类型</param>
102 /// <param name="value">实体类型实例</param>
103 /// <returns></returns>
104 public int Add(Type type, object value)
105 {
106 IDataParameter[] param = null;
107 string sql = Factory.CreateInsertSql(type,value,out param);
108 using (IDbProvider provider = new SqlProvider())
109 {
110 return BaseHelper.ExecuteNonQuery(provider, sql, param);
111 }
112 }
113
114 /// <summary>
115 /// 根据实体公共接口修改该实体信息
116 /// 该实体是根据主键修改
117 /// </summary>
118 /// <param name="entity">实体公共接口</param>
119 /// <returns></returns>
120 public int Update(IEntity entity)
121 {
122 IDataParameter[] param = null;
123 string sql = Factory.CreateUpdateSql(entity,out param);
124 using (IDbProvider provider = new SqlProvider())
125 {
126 return BaseHelper.ExecuteNonQuery(provider, sql, param);
127 }
128 }
129
130 /// <summary>
131 /// 根据实体的某个属性修改数据
132 /// entity 中必须包含该属性,而且该属性的
133 /// 值不能为空
134 /// </summary>
135 /// <param name="entity">实体公共接口</param>
136 /// <param name="propertyName">实体属性名称</param>
137 /// <returns></returns>
138 public int Update(IEntity entity, string propertyName)
139 {
140 IDataParameter[] param = null;
141 string sql = Factory.CreateUpdateSql(entity, out param, propertyName);
142 using (IDbProvider provider = new SqlProvider())
143 {
144 return BaseHelper.ExecuteNonQuery(provider, sql, param);
145 }
146 }
147
148 /// <summary>
149 /// 根据实体的多个属性修改数据
150 /// 数组中的属性名称必须存在.
151 /// 传递参数数组不能为null
152 /// </summary>
153 /// <param name="entity">实体公共接口</param>
154 /// <param name="propertyNames">属性名称数组</param>
155 /// <returns></returns>
156 public int Update(IEntity entity, string[] propertyNames)
157 {
158 IDataParameter[] param = null;
159 string sql = Factory.CreateUpdateSql(entity,out param,propertyNames);
160 using (IDbProvider provider = new SqlProvider())
161 {
162 return BaseHelper.ExecuteNonQuery(provider, sql, param);
163 }
164 }
165
166 /// <summary>
167 /// 修改实体信息
168 /// 该实体是根据主键修改
169 /// </summary>
170 /// <typeparam name="T">实体泛型类型</typeparam>
171 /// <param name="t">泛型实例</param>
172 /// <returns></returns>
173 public int Update<T>(T t) where T : IEntity
174 {
175 IDataParameter[] param = null;
176 string sql = Factory.CreateUpdateSql(typeof(T),t,out param);
177 using (IDbProvider provider = new SqlProvider())
178 {
179 return BaseHelper.ExecuteNonQuery(provider, sql, param);
180 }
181 }
182
183 /// <summary>
184 /// 根据泛型类的某个实体属性来修改该数据。
185 /// 泛型实体实例中该属性不能为空
186 /// </summary>
187 /// <typeparam name="T">泛型类</typeparam>
188 /// <param name="t">泛型实例</param>
189 /// <param name="propertyName"></param>
190 /// <returns></returns>
191 public int Update<T>(T t, string propertyName) where T : IEntity
192 {
193 IDataParameter[] param = null;
194 string sql = Factory.CreateUpdateSql(typeof(T), t, out param,propertyName);
195 using (IDbProvider provider = new SqlProvider())
196 {
197 return BaseHelper.ExecuteNonQuery(provider, sql, param);
198 }
199 }
200
201 /// <summary>
202 /// 根据实体的多个属性修改数据
203 /// 数组中的属性名称在泛型类中必须存在,
204 /// 数组不能传递null值
205 /// </summary>
206 /// <typeparam name="T">泛型类</typeparam>
207 /// <param name="t">泛型实例</param>
208 /// <param name="propertyNames">属性名称数组</param>
209 /// <returns></returns>
210 public int Update<T>(T t, string[] propertyNames) where T : IEntity
211 {
212 IDataParameter[] param = null;
213 string sql = Factory.CreateUpdateSql(typeof(T), t, out param, propertyNames);
214 using (IDbProvider provider = new SqlProvider())
215 {
216 return BaseHelper.ExecuteNonQuery(provider, sql, param);
217 }
218 }
219
220 /// <summary>
221 /// 修改实体信息
222 /// 该实体是根据主键修改
223 /// </summary>
224 /// <param name="type">实体类型</param>
225 /// <param name="value">实体对象实例</param>
226 /// <returns></returns>
227 public int Update(Type type, object value)
228 {
229 IDataParameter[] param = null;
230 string sql = Factory.CreateUpdateSql(type,value,out param);
231 using (IDbProvider provider = new SqlProvider())
232 {
233 return BaseHelper.ExecuteNonQuery(provider, sql, param);
234 }
235 }
236
237 /// <summary>
238 /// 根据实体的某个属性来修改数据信息
239 /// 该方法使用Type 来确定需要修改的实体对象
240 /// value 实例中必须包含propertyName 这个属性
241 /// 而且propertyName 属性值不能为空
242 /// </summary>
243 /// <param name="type">实体类型</param>
244 /// <param name="value">实体实例</param>
245 /// <param name="propertyName">属性名称</param>
246 /// <returns></returns>
247 public int Update(Type type, object value, string propertyName)
248 {
249 IDataParameter[] param = null;
250 string sql = Factory.CreateUpdateSql(type, value, out param, propertyName);
251 using (IDbProvider provider = new SqlProvider())
252 {
253 return BaseHelper.ExecuteNonQuery(provider, sql, param);
254 }
255 }
256
257 /// <summary>
258 /// 根据实体的多个属性来修改数据信息
259 /// 该方法使用Type 来确定需要修改的实体对象
260 /// 数组中的属性名称在泛型类中必须存在,
261 /// 而且数组传递参数不能为null
262 /// </summary>
263 /// <param name="type">实体类型</param>
264 /// <param name="value">实体实例</param>
265 /// <param name="propertyNames">属性名称数组</param>
266 /// <returns></returns>
267 public int Update(Type type, object value, string[] propertyNames)
268 {
269 IDataParameter[] param = null;
270 string sql = Factory.CreateUpdateSql(type, value, out param, propertyNames);
271 using (IDbProvider provider = new SqlProvider())
272 {
273 return BaseHelper.ExecuteNonQuery(provider, sql, param);
274 }
275 }
276
277
278
279
280 /// <summary>
281 /// 删除实体对象
282 /// 该方法是根据实体对象主键删除数据
283 /// </summary>
284 /// <param name="entity">实体公共接口</param>
285 /// <returns></returns>
286 public int Delete(IEntity entity)
287 {
288 IDataParameter[] param = null;
289 string sql = Factory.CreateDeleteSql(entity,out param);
290 using (IDbProvider provider = new SqlProvider())
291 {
292 return BaseHelper.ExecuteNonQuery(provider, sql, param);
293 }
294 }
295
296 /// <summary>
297 /// 根据某个实体属性删除数据
298 /// 该实体必须包含指定的属性名称
299 /// 而且实体属性值不能为空
300 /// </summary>
301 /// <param name="entity">实体属性公共接口</param>
302 /// <param name="propertyName">实体属性名称</param>
303 /// <returns></returns>
304 public int Delete(IEntity entity, string propertyName)
305 {
306 IDataParameter[] param = null;
307 string sql = Factory.CreateDeleteSql(entity,out param,propertyName);
308 using (IDbProvider provider = new SqlProvider())
309 {
310 return BaseHelper.ExecuteNonQuery(provider, sql, param);
311 }
312 }
313
314 /// <summary>
315 /// 根据实体多个属性删除数据
316 /// 实体中必须包含该属性
317 /// 传递参数数组不能为空
318 /// </summary>
319 /// <param name="entity">实体属性公共接口</param>
320 /// <param name="propertyNames">实体属性名称数组</param>
321 /// <returns></returns>
322 public int Delete(IEntity entity, string[] propertyNames)
323 {
324 IDataParameter[] param = null;
325 string sql = Factory.CreateDeleteSql(entity, out param, propertyNames);
326 using (IDbProvider provider = new SqlProvider())
327 {
328 return BaseHelper.ExecuteNonQuery(provider, sql, param);
329 }
330 }
331
332 /// <summary>
333 /// 根据泛型类删除数据
334 /// 该方法是根据实体的主键删除的
335 /// </summary>
336 /// <typeparam name="T">泛型类</typeparam>
337 /// <param name="t">泛型实例</param>
338 /// <returns></returns>
339 public int Delete<T>(T t) where T : class
340 {
341 IDataParameter[] param = null;
342 string sql = Factory.CreateDeleteSql(typeof(T), t, out param);
343 using (IDbProvider provider = new SqlProvider())
344 {
345 return BaseHelper.ExecuteNonQuery(provider, sql, param);
346 }
347 }
348
349 /// <summary>
350 /// 根据泛型类的某个属性删除数据
351 /// 泛型类中必须存在该属性,而且
352 /// 属性值不能为空
353 /// </summary>
354 /// <typeparam name="T">泛型类型</typeparam>
355 /// <param name="t">泛型类实例</param>
356 /// <param name="propertyName">属性名称</param>
357 /// <returns></returns>
358 public int Delete<T>(T t, string propertyName) where T : class
359 {
360 IDataParameter[] param = null;
361 string sql = Factory.CreateDeleteSql(typeof(T), t, out param,propertyName);
362 using (IDbProvider provider = new SqlProvider())
363 {
364 return BaseHelper.ExecuteNonQuery(provider, sql, param);
365 }
366 }
367
368 /// <summary>
369 /// 根据泛型类型的多个属性删除数据
370 /// 泛型类型中必须存在这些属性,传
371 /// 递参数的时候不能为null
372 /// </summary>
373 /// <typeparam name="T">泛型类</typeparam>
374 /// <param name="t">泛型实例</param>
375 /// <param name="propertyNames">属性名称数组</param>
376 /// <returns></returns>
377 public int Delete<T>(T t, string[] propertyNames) where T : class
378 {
379 IDataParameter[] param = null;
380 string sql = Factory.CreateDeleteSql(typeof(T), t, out param, propertyNames);
381 using (IDbProvider provider = new SqlProvider())
382 {
383 return BaseHelper.ExecuteNonQuery(provider, sql, param);
384 }
385 }
386
387 /// <summary>
388 /// 根据实体的类型删除数据。
389 /// value 中的类型由type确定
390 /// </summary>
391 /// <param name="type">实体类型</param>
392 /// <param name="value">实体对象实例</param>
393 /// <returns></returns>
394 public int Delete(Type type, object value)
395 {
396 IDataParameter[] param = null;
397 string sql = Factory.CreateDeleteSql(type,value,out param);
398 using (IDbProvider provider = new SqlProvider())
399 {
400 return BaseHelper.ExecuteNonQuery(provider, sql, param);
401 }
402 }
403
404 /// <summary>
405 /// 根据实体的类型的某个属性删除数据。
406 /// value 中的类型由type确定
407 /// propertyName 属性名称必须在value
408 /// 对象中存在
409 /// </summary>
410 /// <param name="type">实体类型</param>
411 /// <param name="value">实体对象实例</param>
412 /// <param name="propertyName">属性名称</param>
413 /// <returns></returns>
414 public int Delete(Type type, object value, string propertyName)
415 {
416 IDataParameter[] param = null;
417 string sql = Factory.CreateDeleteSql(type, value, out param,propertyName);
418 using (IDbProvider provider = new SqlProvider())
419 {
420 return BaseHelper.ExecuteNonQuery(provider, sql, param);
421 }
422 }
423
424 /// <summary>
425 /// 根据实体的类型的某个属性删除数据。
426 /// value 中的类型由type确定
427 /// propertyName 属性名称必须在value
428 /// 对象中存在
429 /// </summary>
430 /// <param name="type">实体类型</param>
431 /// <param name="value">实体对象实例</param>
432 /// <param name="propertyNames">属性名称数组</param>
433 /// <returns></returns>
434 public int Delete(Type type, object value, string[] propertyNames)
435 {
436 IDataParameter[] param = null;
437 string sql = Factory.CreateDeleteSql(type, value, out param, propertyNames);
438 using (IDbProvider provider = new SqlProvider())
439 {
440 return BaseHelper.ExecuteNonQuery(provider, sql, param);
441 }
442 }
443
444 /// <summary>
445 /// 根据主键查询实体对象
446 /// </summary>
447 /// <typeparam name="T">泛型类型</typeparam>
448 /// <param name="pkPropertyValue">主键值</param>
449 /// <returns></returns>
450 public T GetEntity<T>(object pkPropertyValue) where T : class
451 {
452 IDataParameter[] param = null;
453 string sql = Factory.CreateSingleSql(typeof(T), pkPropertyValue, out param);
454 using (IDbProvider provider = new SqlProvider())
455 {
456 return BaseHelper.ConvertToEntity<T>(BaseHelper.ExecuteDataReader(provider,sql,param));
457 }
458 }
459
460 /// <summary>
461 /// 根据实体类的类型和主键值查询实体对象
462 /// 使用 type 确定实体,主键确定数据的唯
463 /// 一性
464 /// </summary>
465 /// <param name="type">实体类型</param>
466 /// <param name="pkPropertyValue">主键值</param>
467 /// <returns></returns>
468 public object GetEntity(Type type, object pkPropertyValue)
469 {
470 IDataParameter[] param = null;
471 string sql = Factory.CreateSingleSql(type,pkPropertyValue,out param);
472 using (IDbProvider provider = new SqlProvider())
473 {
474 return baseHelper.ConvertToEntity(type,BaseHelper.ExecuteDataReader(provider,sql,param));
475 }
476 }
477
478 /// <summary>
479 /// 根据某个实体的属性来查询实体对象
480 /// 该属性值能确定数据库唯一数据行
481 /// </summary>
482 /// <typeparam name="T">实体泛型类</typeparam>
483 /// <param name="propertyName">属性名称</param>
484 /// <param name="propertyValue">属性值</param>
485 /// <returns></returns>
486 public T GetEntity<T>(string propertyName, object propertyValue) where T : class
487 {
488 IDataParameter[] param = null;
489 string sql = Factory.CreateQueryByPropertySql(typeof(T),propertyName,propertyValue,out param);
490 using (IDbProvider provider = new SqlProvider())
491 {
492 return BaseHelper.ConvertToEntity<T>(BaseHelper.ExecuteDataReader(provider,sql,param));
493 }
494 }
495
496 /// <summary>
497 /// 根据某个实体的属性来查询实体对象
498 /// 该属性值能确定数据库唯一数据行
499 /// </summary>
500 /// <param name="type">实体类型</param>
501 /// <param name="propertyName">属性名称</param>
502 /// <param name="propertyValue">属性值</param>
503 /// <returns></returns>
504 public object GetEntity(Type type, string propertyName, object propertyValue)
505 {
506 IDataParameter[] param = null;
507 string sql = Factory.CreateQueryByPropertySql(type, propertyName, propertyValue, out param);
508 using (IDbProvider provider = new SqlProvider())
509 {
510 return BaseHelper.ConvertToEntity(type,BaseHelper.ExecuteDataReader(provider,sql,param));
511 }
512 }
513
514 /// <summary>
515 /// 根据某个实体的多个属性来查询实体对象
516 /// </summary>
517 /// <typeparam name="T">泛型类</typeparam>
518 /// <param name="entity">实体公共接口</param>
519 /// <param name="propertyNames">属性名称数组</param>
520 /// <returns></returns>
521 public T GetEntity<T>(IEntity entity, string[] propertyNames) where T : class
522 {
523 IDataParameter[] param = null;
524 string sql = Factory.CreateSingleSql(entity,out param,propertyNames);
525 using (IDbProvider provider = new SqlProvider())
526 {
527 return BaseHelper.ConvertToEntity<T>(BaseHelper.ExecuteDataReader(provider,sql,param));
528 }
529 }
530
531 /// <summary>
532 /// 根据某个实体的多个属性来查询实体对象
533 /// 实体根据type类型来确定
534 /// </summary>
535 /// <param name="type">实体类型</param>
536 /// <param name="entity">实体公共接口</param>
537 /// <param name="propertyNames">属性名称数组</param>
538 /// <returns></returns>
539 public object GetEntity(Type type, IEntity entity, string[] propertyNames)
540 {
541 IDataParameter[] param = null;
542 string sql = Factory.CreateSingleSql(type,entity,out param,propertyNames);
543 using (IDbProvider provider = new SqlProvider())
544 {
545 return BaseHelper.ConvertToEntity(type,BaseHelper.ExecuteDataReader(provider,sql,param));
546 }
547 }
548
549
550 /// <summary>
551 /// 查询该类型实体数据行数
552 /// </summary>
553 /// <param name="type">实体类型</param>
554 /// <returns></returns>
555 public int GetCount(Type type)
556 {
557 string sql = Factory.CreateConverageSql(type,Converage.Count);
558 using (IDbProvider provider = new SqlProvider())
559 {
560 return (int)BaseHelper.ExecuteScalar(provider,sql);
561 }
562 }
563
564 /// <summary>
565 /// 查询该类型实体数据行数
566 /// </summary>
567 /// <typeparam name="T">泛型类型</typeparam>
568 /// <returns></returns>
569 public int GetCount<T>() where T : class
570 {
571 string sql = Factory.CreateConverageSql(typeof(T), Converage.Count);
572 using (IDbProvider provider = new SqlProvider())
573 {
574 return (int)BaseHelper.ExecuteScalar(provider, sql);
575 }
576 }
577
578 /// <summary>
579 /// 根据条件查询实体数据行数
580 /// </summary>
581 /// <param name="type">实体类型</param>
582 /// <param name="dic">实体属性键值对</param>
583 /// <param name="component">查询组件</param>
584 /// <returns></returns>
585 public int GetCount(Type type, IDictionary<string, object> dic, ConditionComponent component)
586 {
587 IDataParameter[] param = null;
588 string sql = Factory.CreateConverageSql(type,Converage.Count,"",dic,out param,component);
589 using (IDbProvider provider = new SqlProvider())
590 {
591 return (int)BaseHelper.ExecuteScalar(provider, sql, param);
592 }
593 }
594
595 /// <summary>
596 /// 查询所有实体集合
597 /// </summary>
598 /// <typeparam name="T">泛型类型</typeparam>
599 /// <returns></returns>
600 public IList<T> GetList<T>() where T : class
601 {
602 string sql = Factory.CreateQuerySql(typeof(T));
603 using (IDbProvider provider = new SqlProvider())
604 {
605 return BaseHelper.ConvertToList<T>(BaseHelper.ExecuteDataReader(provider,sql));
606 }
607 }
608
609 /// <summary>
610 /// 根据某个实体属性查询实体集合
611 /// </summary>
612 /// <typeparam name="T">泛型类型</typeparam>
613 /// <param name="propertyName">属性名称</param>
614 /// <param name="value">属性值</param>
615 /// <returns></returns>
616 public IList<T> GetList<T>(string propertyName, object value) where T : class
617 {
618 IDataParameter[] param = null;
619 string sql = Factory.CreateQueryByPropertySql(typeof(T),propertyName,value,out param);
620 using (IDbProvider provider = new SqlProvider())
621 {
622 return BaseHelper.ConvertToList<T>(BaseHelper.ExecuteDataReader(provider, sql,param));
623 }
624 }
625
626
627 /// <summary>
628 /// 根据多个属性查询实体集合
629 /// </summary>
630 /// <typeparam name="T">泛型类型</typeparam>
631 /// <param name="entity">实体公共接口</param>
632 /// <param name="propertyNames">属性名称</param>
633 /// <returns></returns>
634 public IList<T> GetList<T>(IDictionary<string,object> dic) where T : class
635 {
636 IDataParameter[] param = null;
637 string sql = Factory.CreateQueryByPropertySql(typeof(T), dic, out param);
638 using (IDbProvider provider = new SqlProvider())
639 {
640 return BaseHelper.ConvertToList<T>(BaseHelper.ExecuteDataReader(provider, sql, param));
641 }
642 }
643
644 /// <summary>
645 /// 根据多个属性查询实体集合
646 /// 该查询方式附加查询组建
647 /// </summary>
648 /// <typeparam name="T">类型类</typeparam>
649 /// <param name="dic">属性键值对</param>
650 /// <param name="component">查询组件</param>
651 /// <returns></returns>
652 public IList<T> GetList<T>(IDictionary<string, object> dic, ConditionComponent component) where T : class
653 {
654 IDataParameter[] param = null;
655 string sql = Factory.CreateQueryByPropertySql(typeof(T),dic,out param,component);
656 using (IDbProvider provider = new SqlProvider())
657 {
658 return BaseHelper.ConvertToList<T>(BaseHelper.ExecuteDataReader(provider, sql, param));
659 }
660 }
661
662 /// <summary>
663 /// 释放对象内存
664 /// </summary>
665 public void Dispose()
666 {
667 GC.SuppressFinalize(this);
668 }
669 }
670 }
671
自定义的数据库操作接口:
2 {
3 /// <summary>
4 /// 用户登录
5 /// </summary>
6 /// <param name="name">用户名</param>
7 /// <param name="pass">用户密码</param>
8 /// <returns></returns>
9 TabUser GetUser(string name, string pass);
10 }
自定义数据库操作类:
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using CommonData.Data.Core.SQLCore;
6 using Office.Entity;
7
8 namespace Office.DAL.DAL
9 {
10 public class TabUserDAL:SqlHelper,ITabUserDAL
11 {
12 /// <summary>
13 /// 用户登录
14 /// </summary>
15 /// <param name="name">用户名</param>
16 /// <param name="pass">用户密码(已经MD5加密)</param>
17 /// <returns></returns>
18 public TabUser GetUser(string name, string pass)
19 {
20 TabUser user = new TabUser();
21 user.UserName = name;
22 user.PassWord = pass;
23 user=GetEntity<TabUser>(user, new string[] { "UserName", "PassWord" });
24 return user;
25 }
26 }
27 }
28
这里的四段代码相信大家都能够明白其结构的定义,一般采用的方式每张表定义一个数据库操作接口和一个实现类,而这个操作接口是继承了公共的数据库操作接口,而且还是使用的泛型类型,使用泛型类型使得数据抽象话,而后面的操作过程刚好有与此泛化过程对应的处理过程,在此就保障了核心的一致,每个自定的数据库操作接口都会去继承公共的数据库操作类和实现自身的接口,因此每个自定的数据库操作类就具有了操作上面定义的操作的所有方法。在这儿结构中,感觉这个地方使用的非常秒,定义的公共接口中定义的操作方法几乎能后满足增删改查的要求,因此这样就实现了一个ORM操作数据库的完整功能,我们就可以不需要过多的去关心数据库到底是怎样去处理这些方式,我们的任何操作方式都是以对象的方式来操作,不用关系底层的细节实现。当然,任何一个ORM框架都不是能够替换所有的数据库操作,有些过于复杂的操作还是需要自定义sql语句来处理。我们只需在自定义的数据库操作接口中定义相应的方法即可,毕竟这个ORM映射框架也结合了自定义的处理过程,使得程序更加的灵活,可以从多角度去处理。看到这里,对于一个稍微大型的项目,相对于ADO.NET 操作是不是减少了很多代码。
这个东西毕竟是一个人写的,漏洞肯定也不少,自己也没有那么多的时间去测试,只能慢慢的等以后去修改,性能方面的提交,数据复杂度的处理等等问题,在后期的过程中会逐渐来解决这些问题,并与大家分享。如果大家有任何疑问可以留言,或者好的建议可以随时联系我。在此谢谢
(注: ORM涉及内容比较多,后续期待,有兴趣的可以与本人探讨)