程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 用C#打造自己的通用數據訪問類庫

用C#打造自己的通用數據訪問類庫

編輯:C#入門知識

說明:此篇文章是給那些和我一樣仍在使用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測試通過,測試截圖如下:

 \

 


因為測試用的代碼涉及到下一篇博文的內容,所以會將測試代碼放到下一篇博文中。



摘自 周公的專欄

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved