說明:此篇文章是給那些和我一樣仍在使用ADO.NET訪問數據庫的.NET開發人員寫的,因為某些原因,比如還在使用.NET3.0以下版本開發.NET應用或者所使用的數據庫對ORM支持不是很好,或者是對ORM的性能有所懷疑(其實在訪問量不是很大的情況下沒有必要過分追求性能的極限)等等,這部分人仍在使用傳統的ADO.NET來訪問數據庫,他們或手寫或采用代碼生成工具來生成實體類和增刪改查的SQL語句,在將DataTable或者DataReader轉換成對應的實體類的時候仍需要一行行寫代碼,本類就是為了解決這個問題的,可以用幾個類來實現方便快捷的轉換。本類庫在SQL Server/MySQL/SQLite下測試通過,由於條件有限未在所有的數據庫下測試,如果有問題請在此留言或者在周公的微博留言(http://weibo.com/zhoufoxcn)。
其實在寫這套類庫之前,去年周公就寫了兩篇有關的文章,一篇叫《用C#打造自己的實體轉換器http://www.BkJia.com/kf/201107/96707.html》,另一篇叫《利用ADO.NET的體系架構打造通用的數據庫訪問通用類http://www.BkJia.com/kf/201204/127767.html》(兩篇文章的閱讀地址會在文末給出),本篇的代碼就是在這兩篇文章的基礎上經過實際應用修改而成,主要是修正了幾個問題:1.如果在SELECT子句的字段中不包含對應實體類的某個屬性,那麼該屬性的值就為它對應Type的默認值(如int,short為0,引用類型為null),而不是像以前那樣用Ignorable,因為有些屬性可能在某個查詢中需要而在另外一個查詢中不需要,采用Ignorable這樣的Attribute的話太武斷;2.修正了在泛型類型時的錯誤;3.在類的屬性類型中除了支持常見數據類型(數值類型、可空類型和string)之外,還支持byte[]這種常見的數據類型。
本類庫共有5個類:DbProviderType、ProviderFactory、DbUtility、EntityReader、ColumnNameAttribute。
其中DbProviderType、ProviderFactory、DbUtility三個類的相關代碼如下:
1. using System;
2. using System.Collections.Generic;
3. using System.Data;
4. using System.Data.Common;
5.
6. namespace NetSkycn.Data
7. {
8. /// <summary>
9. /// 通用數據庫訪問類,封裝了對數據庫的常見操作
10. ///
11. ///
12. ///
13. /// www.2cto.com
14. /// </summary>
15. public sealed class DbUtility
16. {
17. public string ConnectionString { get; set; }
18. private DbProviderFactory providerFactory;
19. /// <summary>
20. /// 構造函數
21. /// </summary>
22. /// <param name="connectionString">數據庫連接字符串</param>
23. /// <param name="providerType">數據庫類型枚舉,參見<paramref name="providerType"/></param>
24. public DbUtility(string connectionString, DbProviderType providerType)
25. {
26. ConnectionString = connectionString;
27. providerFactory = ProviderFactory.GetDbProviderFactory(providerType);
28. if (providerFactory == null)
29. {
30. throw new ArgumentException("Can't load DbProviderFactory for given value of providerType");
31. }
32. }
33. /// <summary>
34. /// 對數據庫執行增刪改操作,返回受影響的行數。
35. /// </summary>
36. /// <param name="sql">要執行的增刪改的SQL語句</param>
37. /// <param name="parameters">執行增刪改語句所需要的參數</param>
38. /// <returns></returns>
39. public int ExecuteNonQuery(string sql, IList<DbParameter> parameters)
40. {
41. return ExecuteNonQuery(sql, parameters, CommandType.Text);
42. }
43. /// <summary>
44. /// 對數據庫執行增刪改操作,返回受影響的行數。
45. /// </summary>
46. /// <param name="sql">要執行的增刪改的SQL語句</param>
47. /// <param name="parameters">執行增刪改語句所需要的參數</param>
48. /// <param name="commandType">執行的SQL語句的類型</param>
49. /// <returns></returns>
50. public int ExecuteNonQuery(string sql, IList<DbParameter> parameters, CommandType commandType)
51. {
52. using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
53. {
54. command.Connection.Open();
55. int affectedRows = command.ExecuteNonQuery();
56. command.Connection.Close();
57. return affectedRows;
58. }
59. }
60.
61. /// <summary>
62. /// 執行一個查詢語句,返回一個關聯的DataReader實例
63. /// </summary>
64. /// <param name="sql">要執行的查詢語句</param>
65. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
66. /// <returns></returns>
67. public DbDataReader ExecuteReader(string sql, IList<DbParameter> parameters)
68. {
69. return ExecuteReader(sql, parameters, CommandType.Text);
70. }
71.
72. /// <summary>
73. /// 執行一個查詢語句,返回一個關聯的DataReader實例
74. /// </summary>
75. /// <param name="sql">要執行的查詢語句</param>
76. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
77. /// <param name="commandType">執行的SQL語句的類型</param>
78. /// <returns></returns>
79. public DbDataReader ExecuteReader(string sql, IList<DbParameter> parameters, CommandType commandType)
80. {
81. DbCommand command = CreateDbCommand(sql, parameters, commandType);
82. command.Connection.Open();
83. return command.ExecuteReader(CommandBehavior.CloseConnection);
84. }
85.
86. /// <summary>
87. /// 執行一個查詢語句,返回一個包含查詢結果的DataTable
88. /// </summary>
89. /// <param name="sql">要執行的查詢語句</param>
90. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
91. /// <returns></returns>
92. public DataTable ExecuteDataTable(string sql, IList<DbParameter> parameters)
93. {
94. return ExecuteDataTable(sql, parameters, CommandType.Text);
95. }
96. /// <summary>
97. /// 執行一個查詢語句,返回一個包含查詢結果的DataTable
98. /// </summary>
99. /// <param name="sql">要執行的查詢語句</param>
100. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
101. /// <param name="commandType">執行的SQL語句的類型</param>
102. /// <returns></returns>
103. public DataTable ExecuteDataTable(string sql, IList<DbParameter> parameters, CommandType commandType)
104. {
105. using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
106. {
107. using (DbDataAdapter adapter = providerFactory.CreateDataAdapter())
108. {
109. adapter.SelectCommand = command;
110. DataTable data = new DataTable();
111. adapter.Fill(data);
112. return data;
113. }
114. }
115. }
116.
117. /// <summary>
118. /// 執行一個查詢語句,返回查詢結果的第一行第一列
119. /// </summary>
120. /// <param name="sql">要執行的查詢語句</param>
121. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
122. /// <returns></returns>
123. public Object ExecuteScalar(string sql, IList<DbParameter> parameters)
124. {
125. return ExecuteScalar(sql, parameters, CommandType.Text);
126. }
127.
128. /// <summary>
129. /// 執行一個查詢語句,返回查詢結果的第一行第一列
130. /// </summary>
131. /// <param name="sql">要執行的查詢語句</param>
132. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
133. /// <param name="commandType">執行的SQL語句的類型</param>
134. /// <returns></returns>
135. public Object ExecuteScalar(string sql, IList<DbParameter> parameters, CommandType commandType)
136. {
137. using (DbCommand command = CreateDbCommand(sql, parameters, commandType))
138. {
139. command.Connection.Open();
140. object result = command.ExecuteScalar();
141. command.Connection.Close();
142. return result;
143. }
144. }
145.
146. /// <summary>
147. /// 查詢多個實體集合
148. /// </summary>
149. /// <typeparam name="T">返回的實體集合類型</typeparam>
150. /// <param name="sql">要執行的查詢語句</param>
151. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
152. /// <returns></returns>
153. public List<T> QueryForList<T>(string sql, IList<DbParameter> parameters) where T : new()
154. {
155. return QueryForList<T>(sql, parameters, CommandType.Text);
156. }
157.
158. /// <summary>
159. /// 查詢多個實體集合
160. /// </summary>
161. /// <typeparam name="T">返回的實體集合類型</typeparam>
162. /// <param name="sql">要執行的查詢語句</param>
163. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
164. /// <param name="commandType">執行的SQL語句的類型</param>
165. /// <returns></returns>
166. public List<T> QueryForList<T>(string sql, IList<DbParameter> parameters, CommandType commandType) where T : new()
167. {
168. DataTable data = ExecuteDataTable(sql, parameters, commandType);
169. return EntityReader.GetEntities<T>(data);
170. }
171. /// <summary>
172. /// 查詢單個實體
173. /// </summary>
174. /// <typeparam name="T">返回的實體集合類型</typeparam>
175. /// <param name="sql">要執行的查詢語句</param>
176. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
177. /// <returns></returns>
178. public T QueryForObject<T>(string sql, IList<DbParameter> parameters) where T : new()
179. {
180. return QueryForObject<T>(sql, parameters, CommandType.Text);
181. }
182.
183. /// <summary>
184. /// 查詢單個實體
185. /// </summary>
186. /// <typeparam name="T">返回的實體集合類型</typeparam>
187. /// <param name="sql">要執行的查詢語句</param>
188. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
189. /// <param name="commandType">執行的SQL語句的類型</param>
190. /// <returns></returns>
191. public T QueryForObject<T>(string sql, IList<DbParameter> parameters, CommandType commandType) where T : new()
192. {
193. return QueryForList<T>(sql, parameters, commandType)[0];
194. }
195.
196. public DbParameter CreateDbParameter(string name, object value)
197. {
198. return CreateDbParameter(name, ParameterDirection.Input, value);
199. }
200.
201. public DbParameter CreateDbParameter(string name, ParameterDirection parameterDirection, object value)
202. {
203. DbParameter parameter = providerFactory.CreateParameter();
204. parameter.ParameterName = name;
205. parameter.Value = value;
206. parameter.Direction = parameterDirection;
207. return parameter;
208. }
209.
210. /// <summary>
211. /// 創建一個DbCommand對象
212. /// </summary>
213. /// <param name="sql">要執行的查詢語句</param>
214. /// <param name="parameters">執行SQL查詢語句所需要的參數</param>
215. /// <param name="commandType">執行的SQL語句的類型</param>
216. /// <returns></returns>
217. private DbCommand CreateDbCommand(string sql, IList<DbParameter> parameters, CommandType commandType)
218. {
219. DbConnection connection = providerFactory.CreateConnection();
220. DbCommand command = providerFactory.CreateCommand();
221. connection.ConnectionString = ConnectionString;
222. command.CommandText = sql;
223. command.CommandType = commandType;
224. command.Connection = connection;
225. if (!(parameters == null || parameters.Count == 0))
226. {
227. foreach (DbParameter parameter in parameters)
228. {
229. command.Parameters.Add(parameter);
230. }
231. }
232. return command;
233. }
234. }
235. /// <summary>
236. /// 數據庫類型枚舉
237. /// </summary>
238. public enum DbProviderType : byte
239. {
240. SqlServer,
241. MySql,
242. SQLite,
243. Oracle,
244. ODBC,
245. OleDb,
246. Firebird,
247. PostgreSql,
248. DB2,
249. Informix,
250. SqlServerCe
251. }
252. /// <summary>
253. /// DbProviderFactory工廠類
254. /// </summary>
255. public class ProviderFactory
256. {
257. private static Dictionary<DbProviderType, string> providerInvariantNames = new Dictionary<DbProviderType, string>();
258. private static Dictionary<DbProviderType, DbProviderFactory> providerFactoies = new Dictionary<DbProviderType, DbProviderFactory>(20);
259. static ProviderFactory()
260. {
261. //加載已知的數據庫訪問類的程序集
262. providerInvariantNames.Add(DbProviderType.SqlServer, "System.Data.SqlClient");
263. providerInvariantNames.Add(DbProviderType.OleDb, "System.Data.OleDb");
264. providerInvariantNames.Add(DbProviderType.ODBC, "System.Data.ODBC");
265. providerInvariantNames.Add(DbProviderType.Oracle, "Oracle.DataAccess.Client");
266. providerInvariantNames.Add(DbProviderType.MySql, "MySql.Data.MySqlClient");
267. providerInvariantNames.Add(DbProviderType.SQLite, "System.Data.SQLite");
268. providerInvariantNames.Add(DbProviderType.Firebird, "FirebirdSql.Data.Firebird");
269. providerInvariantNames.Add(DbProviderType.PostgreSql, "Npgsql");
270. providerInvariantNames.Add(DbProviderType.DB2, "IBM.Data.DB2.iSeries");
271. providerInvariantNames.Add(DbProviderType.Informix, "IBM.Data.Informix");
272. providerInvariantNames.Add(DbProviderType.SqlServerCe, "System.Data.SqlServerCe");
273. }
274. /// <summary>
275. /// 獲取指定數據庫類型對應的程序集名稱
276. /// </summary>
277. /// <param name="providerType">數據庫類型枚舉</param>
278. /// <returns></returns>
279. public static string GetProviderInvariantName(DbProviderType providerType)
280. {
281. return providerInvariantNames[providerType];
282. }
283. /// <summary>
284. /// 獲取指定類型的數據庫對應的DbProviderFactory
285. /// </summary>
286. /// <param name="providerType">數據庫類型枚舉</param>
287. /// <returns></returns>
288. public static DbProviderFactory GetDbProviderFactory(DbProviderType providerType)
289. {
290. //如果還沒有加載,則加載該DbProviderFactory
291. if (!providerFactoies.ContainsKey(providerType))
292. {
293. providerFactoies.Add(providerType, ImportDbProviderFactory(providerType));
294. }
295. return providerFactoies[providerType];
296. }
297. /// <summary>
298. /// 加載指定數據庫類型的DbProviderFactory
299. /// </summary>
300. /// <param name="providerType">數據庫類型枚舉</param>
301. /// <returns></returns>
302. private static DbProviderFactory ImportDbProviderFactory(DbProviderType providerType)
303. {
304. string providerName = providerInvariantNames[providerType];
305. DbProviderFactory factory = null;
306. try
307. {
308. //從全局程序集中查找
309. factory = DbProviderFactories.GetFactory(providerName);
310. }
311. catch (ArgumentException e)
312. {
313. factory = null;
314. }
315. return factory;
316. }
317. }
318. }
其中EntityReader、ColumnNameAttribute的代碼如下:
沒辦法,不能在這裡粘貼全部代碼,所以放在附件下載了,這不是我的錯,請大家諒解。
本類庫經過NUnit測試通過,測試截圖如下: