使用ado.net打造通用的數據庫操做類

最近在項目中使用中碰到了這樣一種狀況,查詢的數據是從Oracle中獲取的,可是記錄下來的數據是存在Sql Server中(企業Oracle數據庫管理太嚴,沒辦法操做)。並且我在以前的工做中也碰到過使用SQLite數據庫,就藉此次機會寫一個通用的類庫。html

我在網上搜到了一篇利用工廠模式實現的通用類庫,我在參考該文章基礎上,作了一些修改。本文最好有一些Ado.net的基礎。面試

感謝埋頭前進的碼農 https://www.cnblogs.com/lifeil/archive/2013/04/16/3024161.html的文章。sql

1.首先建立數據庫的枚舉類型數據庫

 1   public enum DbProviderType : byte
 2        {
 3            // <summary>
 4            /// 微軟 SqlServer 數據庫
 5            /// </summary>
 6            SqlServer,
 7 
 8            /// <summary>
 9            /// 開源 MySql數據庫
10            /// </summary>
11            MySql,
12 
13            /// <summary>
14            /// 嵌入式輕型數據庫 SQLite
15            /// </summary>
16            SQLite,
17 
18            /// <summary>
19            /// 甲骨文 Oracle
20            /// </summary>
21            Oracle,
22 
23              /// <summary>
24            /// 舊版微軟的oracle組件,目前已經廢棄
25            /// </summary>
26            OracleClient,
27 
28            /// <summary>
29            /// 開放數據庫互連
30            /// </summary>
31            ODBC,
32 
33            /// <summary>
34            /// 面向不一樣的數據源的低級應用程序接口
35            /// </summary>
36            OleDb,
37 
38            /// <summary>
39            /// 跨平臺的關係數據庫系統 Firebird
40            /// </summary>
41            Firebird,
42 
43            /// <summary>
44            ///加州大學伯克利分校計算機系開發的關係型數據庫 PostgreSql
45            /// </summary>
46            PostgreSql,
47 
48            /// <summary>
49            /// IBM出口的一系列關係型數據庫管理系統 DB2
50            /// </summary>
51            DB2,
52 
53            /// <summary>
54            /// IBM公司出品的關係數據庫管理系統(RDBMS)家族  Informix
55            /// </summary>
56            Informix,
57 
58            /// <summary>
59            /// 微軟推出的一個適用於嵌入到移動應用的精簡數據庫產品 SqlServerCe
60            /// </summary>
61            SqlServerCe
62        }

2.建立好後,咱們再設計一個ProviderFactory類,該類能夠根據傳過來的DbProviderType,建立不一樣的DbProviderFactory 對象,該對象用於通常的數據庫操做。oracle

 1  public  class ProviderFactory
 2     {
 3       /// <summary>
 4       /// 保存每種數據訪問方式對應的程序集名稱
 5       /// </summary>
 6       private static Dictionary<MyHelper.Define.DbProviderType,string> providerInvariantNames =new   Dictionary<MyHelper.Define.DbProviderType,string>();
 7 
 8       /// <summary>
 9       /// 保存已經生成的DbProviderFactory對象
10       /// </summary>
11       private readonly static Dictionary<MyHelper.Define.DbProviderType, DbProviderFactory> providerFactoies = new Dictionary<MyHelper.Define.DbProviderType, DbProviderFactory>(20);
12 
13       /// <summary>
14       /// 加載已知的訪問類型與名稱
15       /// </summary>
16       static ProviderFactory()
17       {
18           providerInvariantNames.Add(MyHelper.Define.DbProviderType.SqlServer, "System.Data.SqlClient");
19           providerInvariantNames.Add(MyHelper.Define.DbProviderType.OleDb, "System.Data.OleDb");
20           providerInvariantNames.Add(MyHelper.Define.DbProviderType.ODBC, "System.Data.ODBC");
21           providerInvariantNames.Add(MyHelper.Define.DbProviderType.OracleClient, "System.Data.OracleClient");//已經廢棄
22           providerInvariantNames.Add(MyHelper.Define.DbProviderType.Oracle, "Oracle.ManagedDataAccess.Client"); //須要安裝Oracle.ManagedDataAccess插件,不然無效
23           providerInvariantNames.Add(MyHelper.Define.DbProviderType.MySql, "MySql.Data.MySqlClient");
24           providerInvariantNames.Add(MyHelper.Define.DbProviderType.SQLite, "System.Data.SQLite"); //注意在Nuget加入SQLite程序集
25           //出現錯誤的話,參考https://www.cnblogs.com/leleroyn/archive/2011/03/24/1993627.html
26           //<remove invariant="System.Data.SQLite"/>
27           //<add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
28           providerInvariantNames.Add(MyHelper.Define.DbProviderType.Firebird, "FirebirdSql.Data.Firebird");
29           providerInvariantNames.Add(MyHelper.Define.DbProviderType.PostgreSql, "Npgsql");
30           providerInvariantNames.Add(MyHelper.Define.DbProviderType.DB2, "IBM.Data.DB2.iSeries");
31           providerInvariantNames.Add(MyHelper.Define.DbProviderType.Informix, "IBM.Data.Informix");
32           providerInvariantNames.Add(MyHelper.Define.DbProviderType.SqlServerCe, "System.Data.SqlServerCe");
33       }
34 
35       public  static DbProviderFactory GetDbProviderFactory(MyHelper.Define.DbProviderType providerType)
36       {
37           if (!providerFactoies.ContainsKey(providerType))
38           {
39               var factory = BuildDbProviderFactory(providerType); //生成DbProviderFactory對象
40               providerFactoies.Add(providerType, factory); //加入到字典中
41           }
42           return providerFactoies[providerType];
43       }
44 
45       /// <summary>
46       /// 生成DbProviderFactory對象
47       /// </summary>
48       /// <param name="providerType"></param>
49       /// <returns></returns>
50       private static DbProviderFactory BuildDbProviderFactory(MyHelper.Define.DbProviderType providerType)
51       {
52           string provideName = providerInvariantNames[providerType]; //程序集名稱;
53           DbProviderFactory factory = null;
54           try
55           {
56               factory = DbProviderFactories.GetFactory(provideName);
57           }
58           catch (Exception ex)
59           {
60               factory = null;
61           }
62           return factory;
63       }

3.建立DbHelper類。ide

  1 public  class DbHelper
  2     {
  3       private  DbProviderFactory _providerFactory;
  4       private string _connectionString = null; //保存鏈接字符串
  5 
  6       /// <summary>
  7       /// 生成DbProviderFactory對象
  8       /// </summary>
  9       /// <param name="connectionString">鏈接字符串</param>
 10       /// <param name="providerType">須要生成的DbProviderFactory對象</param>
 11       public DbHelper(string connectionString,MyHelper.Define.DbProviderType providerType)
 12       {
 13           if (string.IsNullOrEmpty(connectionString)) //鏈接字符串不能爲空
 14           {
 15               throw new ArgumentException("connectionString is not null");
 16           }
 17           _providerFactory = ProviderFactory.GetDbProviderFactory(providerType);  //獲取到生成的DbProviderFactory對象
 18           _connectionString = connectionString;
 19           if (_providerFactory == null)
 20           {
 21               throw new ArgumentException("can't build DbProviderFactory, please check DbProviderType ");
 22           }
 23       }
 24 
 25       /// <summary>
 26       /// 判斷數據庫是否能夠打開
 27       /// </summary>
 28       /// <returns></returns>
 29       public bool CanOpen()
 30       {
 31             var dbConnection= _providerFactory.CreateConnection();
 32             dbConnection.ConnectionString = _connectionString;
 33             try
 34             {
 35                 dbConnection.Open(); //打開鏈接
 36                 return true;
 37 
 38             }
 39             catch (Exception ex)
 40             {
 41                 return false;
 42             }
 43             finally
 44             {
 45                 dbConnection.Close();  //關閉鏈接
 46             }
 47       }
 48 
 49       /// <summary>
 50       /// 
 51       /// </summary>
 52       /// <returns></returns>
 53       public DbConnection GetDbConnection()
 54       {
 55         var connection=  _providerFactory.CreateConnection();
 56         connection.ConnectionString = _connectionString;
 57         return connection;
 58       }
 59 
 60       /// <summary>
 61       /// 執行增刪改的方法
 62       /// </summary>
 63       /// <param name="sqlString">sql語句</param>
 64       /// <param name="dbParameters">參數</param>
 65       /// <param name="commandType">執行方式,是Sql語句仍是存儲過程</param>
 66       /// <returns></returns>
 67       public int ExecuteNonQuery(string sqlString ,DbParameter[] dbParameters,CommandType commandType)
 68       {
 69           int result;
 70           using (DbConnection connection = GetDbConnection())
 71           {
 72               using (DbCommand command = CreateDbQueryCommand(connection, sqlString, dbParameters, commandType))
 73               {
 74                   connection.Open();
 75                   result= command.ExecuteNonQuery();
 76                   connection.Close();
 77               }
 78           }
 79 
 80           return result;
 81       }
 82 
 83 
 84       /// <summary>
 85       /// 執行查詢語句,返回DataSet
 86       /// </summary>
 87       /// <param name="sqlString"></param>
 88       /// <param name="dbParameters"></param>
 89       /// <param name="commandType"></param>
 90       /// <returns></returns>
 91       public DataSet ExecuteQuery(string sqlString, DbParameter[] dbParameters, CommandType commandType)
 92       {
 93           DataSet dataSet=new DataSet();
 94           using (DbConnection connection = GetDbConnection())
 95           {
 96               using(DbDataAdapter adapter=_providerFactory.CreateDataAdapter())
 97               {
 98                   adapter.SelectCommand=CreateDbQueryCommand(connection,sqlString,dbParameters,commandType);
 99                   connection.Open();
100                   adapter.Fill(dataSet);
101                   connection.Close();
102               }
103           }
104           return dataSet;
105       }
106 
107       private DbCommand CreateDbQueryCommand(DbConnection connection, string sqlString, IDbDataParameter[] dbParameters, CommandType commandType)
108       {
109         return   CreateDbCommand(connection, sqlString, dbParameters, commandType, null);
110       }
111 
112       /// <summary>
113       /// 建立DbCommand對象
114       /// </summary>
115       /// <param name="connection">DbConnection對象</param>
116       /// <param name="sqlString">查詢語句</param>
117       /// <param name="dbParameters">參數</param>
118       /// <param name="commandType">類型</param>
119       /// <param name="dbTransaction">事務</param>
120       /// <returns></returns>
121       public  DbCommand CreateDbCommand(DbConnection connection, string sqlString, IDbDataParameter[] dbParameters, CommandType commandType,DbTransaction dbTransaction)
122       {
123           DbCommand command = _providerFactory.CreateCommand();
124           if (dbTransaction != null)
125           {
126               command.Transaction = dbTransaction;
127           }
128           command.CommandText = sqlString;
129           command.CommandType = commandType;
130           command.Connection = connection;
131           if (dbParameters != null)
132           {
133               command.Parameters.AddRange(dbParameters);
134           }
135           return command;
136       }
137 
138 
139       /// <summary>
140       /// 返回第一行第一列的數據,通常用於執行聚合操做的語句
141       /// </summary>
142       /// <param name="sqlString">查詢語句</param>
143       /// <param name="dbParameters">參數</param>
144       /// <param name="commandType">Sql語句仍是存儲過程</param>
145       /// <returns></returns>
146       public object ExecuteScalar(string sqlString, DbParameter[] dbParameters, CommandType commandType)
147       {
148           object result;
149           using (DbConnection connection = GetDbConnection())
150           {
151               using (DbCommand command = CreateDbQueryCommand(connection, sqlString, dbParameters, commandType))
152               {
153                   connection.Open();
154                   result = command.ExecuteScalar();
155                   connection.Close();
156               }
157           }
158           return result;
159       }

方法的說明已經的很清楚了,有點Ado.net基礎的同窗應該都能看的懂。測試

下面進入咱們的測試階段,在這兒咱們重點以Sql Server作測試,也會測試一下Oracle數據庫和SQLite數據庫。ui

首先咱們建立一個TestDb的數據庫,再建立一張Users表。spa

咱們在建立一個存儲過程,該存過過程根據傳進來的ID值,返回Name字段。.net

下面是存儲過程的代碼:

1 Create procedure [dbo].[GetUser]
2  @id    varchar(30),
3  @name varchar(30) output
4  as
5  begin
6     select @name=name  from Users where id=@id
7  end

如今開始測試。

首先咱們先執行ExecuteQuery方法,該方法返回DataSet對象。

 1  var connectionString = @"Server=.;Initial Catalog=TestDB;User ID=sa;Password=123456;";
 2             DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.SqlServer);
 3             string text = "select * from users ";
 4 
 5             var usersDataSet = dbHelper.ExecuteQuery(text, null, CommandType.Text);
 6 
 7             for (int i = 0; i < usersDataSet.Tables[0].Rows.Count; i++)
 8             {
 9                 Console.WriteLine("ID:{0},名字:{1}", usersDataSet.Tables[0].Rows[i][0], usersDataSet.Tables[0].Rows[i][1]);
10             }
11 
12 
13             Console.ReadKey();

結果:

執行ExecuteScalar方法,這兒咱們查詢出Users這張表的總數量。

1   var connectionString = @"Server=.;Initial Catalog=TestDB;User ID=sa;Password=123456;";
2             DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.SqlServer);
3             string text = "select  count(*) from  users ";
4 
5             var count = (int)dbHelper.ExecuteScalar(text, null, CommandType.Text);
6             Console.WriteLine("總數量:" + count.ToString());
7 
8             Console.ReadKey();

結果

執行ExecuteNonQuery方法,在這兒咱們執行帶有返回參數的存儲過程。

 1    var connectionString = @"Server=.;Initial Catalog=TestDB;User ID=sa;Password=123456;";
 2             DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.SqlServer);
 3             string text = "GetUser ";
 4             DbParameter[] parameters = new DbParameter[]
 5              {
 6                  new SqlParameter("@id", SqlDbType.VarChar){ Value="1"},
 7                  new SqlParameter("@name", SqlDbType.VarChar){ Direction=ParameterDirection.Output,Size=30}
 8              };
 9             dbHelper.ExecuteNonQuery(text, parameters, CommandType.StoredProcedure);
10             Console.WriteLine("名字:" + parameters[1].Value);
11 
12             Console.ReadKey();

上面的三種方法,咱們都已經測試完成,沒有任何問題。

下面咱們來替換使用其餘數據庫繼續測試。

Oracle數據庫:

在測試前須要在Nuget中加入Oracle.ManagedDataAccess程序集,不然會出現錯誤。

 

 

 

 

 1   var connectionString = @"Password=lisi;User ID=lisi;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.229.138)
 2                                                     (PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=MLDN)))";
 3             DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.Oracle);
 4             string text = "select * from users ";
 5 
 6             var usersDataSet = dbHelper.ExecuteQuery(text, null, CommandType.Text);
 7 
 8             for (int i = 0; i < usersDataSet.Tables[0].Rows.Count; i++)
 9             {
10                 Console.WriteLine("ID:{0},名字:{1}", usersDataSet.Tables[0].Rows[i][0], usersDataSet.Tables[0].Rows[i][1]);
11             }
12 
13 
14             Console.ReadKey();

結果

OK,Oracle也沒問題。

下面試試看SQLite數據庫。

該方法也須要在Nuget中加入SQLite的的插件:

若是不加入的話,會出現如下錯誤:

在裝好後,不必定能使用起來,仍是出現以上錯誤

則在Config文件DbProviderFactories節點中加入一段代碼就能夠了。

  <remove invariant="System.Data.SQLite"/>
      <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".Net Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />

 

代碼:

 1      var connectionString = @"data source=mydb.db";
 2             DbHelper dbHelper = new DbHelper(connectionString, MyHelper.Define.DbProviderType.SQLite);
 3 
 4             //string text = "create table users(id varchar(20),name varchar(20)); ";
 5             //dbHelper.ExecuteNonQuery(text, null, CommandType.Text); //建立表
 6 
 7             //string sql1 = "insert into users values('1','zhangsan')";
 8             //string sql2 = "insert into users values('2','lisi')";
 9             //dbHelper.ExecuteNonQuery(sql1, null, CommandType.Text); //建立表
10             //dbHelper.ExecuteNonQuery(sql2, null, CommandType.Text); //建立表
11 
12             string selectSql = "select * from users";
13             var usersDataSet = dbHelper.ExecuteQuery(selectSql, null, CommandType.Text);
14             for (int i = 0; i < usersDataSet.Tables[0].Rows.Count; i++)
15             {
16                 Console.WriteLine("ID:{0},名字:{1}", usersDataSet.Tables[0].Rows[i][0], usersDataSet.Tables[0].Rows[i][1]);
17             }
18 
19             Console.ReadKey();

在代碼中我加入了建立表和插入數據的語句,該段代碼被我註釋了,若是想要測試的話,執行一次就能夠了。

以上初步測試了SQL Server,Oracle和SQLite三種數據庫。

參考文章:

https://www.cnblogs.com/leleroyn/archive/2011/03/24/1993627.html

https://www.cnblogs.com/gguozhenqian/p/4262813.html

https://www.cnblogs.com/lifeil/archive/2013/04/16/3024161.html

相關文章
相關標籤/搜索