用設計模式開發通用資料庫操作器 (轉)

themoney發表於2007-10-04
用設計模式開發通用資料庫操作器 (轉)[@more@]
  我們都希望在開發的時候能少寫一些程式碼,希望能到處使用,希望不用管什麼樣的軟體都能用,我們該怎麼辦呢?

我們運算元據庫時用到些什麼類

  一般來說,我們對資料庫進行操作時都會用到一些類,下面我就對著些類做個總結:
1.  Server:
a)  System.Data.SqlClient.SqlDataAdapterSQL資料介面卡。表示用於填充 /MS.MSDNQTR.2003FEB.2052/cpref/html/frlrfsystemdatadatasetclasstopic.htm">DataSet 和 資料庫的一組資料命令和一個資料庫連線。無法繼承此類。該類繼承於System.Data.Common.DataAdapter和實現介面System.Data.IDbDataAdapter採用Adapter設計。
b)  System.Data.SqlClient.SqlConnectionSQL資料庫連線。表示 SQL Server 資料庫的一個開啟的連線。無法繼承此類。
c)  System.Data.SqlClient.SqlCommandBuilderSQL資料庫命令生成器。自動生成具有以下用途的單表命令:使對 所做的更改與關聯的 SQL Server 資料庫相協調。無法繼承此類。採用Builder模式設計。
另外還有一些,但是在本文中將用不到,所以這裡也就不再敘述了。
2.  :
a)  System.Data.OracleClient.OracleDataAdapterOracle資料介面卡。表示用於填充 DataSet 和更新Oracle資料庫的一組資料命令和到資料庫的連線。無法繼承此類。該類繼承於System.Data.Common.DbDataAdapter和實現介面System.Data.IDbDataAdapter採用Adapter模式設計。
b)  System.Data.OracleClient.OracleConnectionOracle資料庫連線。表示一個到Oracle資料庫的開啟的連線。無法繼承此類。
c)  System.Data.OracleClient.OracleCommandBuilder:Oracle資料庫命令生成器。自動生成用於協調 DataSet 的更改與關聯的Oracle資料庫的單表命令。無法繼承此類。採用Builder模式設計。
3.  Odbc:
a)  System.Data.Odbc.OdbcDataAdapterOdbc型別資料資料介面卡。表示資料命令集和到Odbc資料來源的連線,它們用於填充 以及更新該資料來源。無法繼承此類。。該類繼承於System.Data.Common.DbDataAdapter和實現介面System.Data.IDbDataAdapter採用Adapter模式設計。
b)  System.Data.Odbc.OdbcConnectionOdbc資料庫連線。表示到Odbc資料來源的連線是開啟的。
c)  System.Data.Odbc.OdbcCommandBuilderOdbc資料庫命令生成器。自動生成用於協調 的更改與關聯的Odbc型別資料來源的單表命令。無法繼承此類。採用Builder模式設計。
4.  OleDb:
a)  System.Data.OleDb.OleDbDataAdapterOdbc型別資料資料介面卡。表示資料命令集和到OleDb資料來源的連線,它們用於填充 以及更新該資料來源。無法繼承此類。。該類繼承於System.Data.Common.DbDataAdapter和實現介面System.Data.IDbDataAdapter採用Adapter模式設計。
b)  System.Data.OleDb.OleDbConnectionOleDb資料庫連線。表示到OleDb資料來源的連線是開啟的。
c)  System.Data.OleDb.OleDbCommandBuilderOleDb資料庫命令生成器。自動生成用於協調 的更改與關聯的OleDb型別資料來源的單表命令。無法繼承此類。採用Builder模式設計。

我們需要什麼樣的資料操作器

  當然是越簡單越好了,功能倒不一定要強大,夠用就行。希望能支援多種資料庫,使用這個操作器的不用再考慮是那種資料庫;希望能對多個資料庫操作,一個專案使用多個資料庫卻不對增加複雜度;希望支援事務,失敗能夠自動回滾。功能嘛,能讀取資料、更新資料就可以了。

通用資料操作器的思路

  對資料庫的操作其實就是兩件事:出和進。出呢就是從資料庫中讀取資料,進就是將資料寫回資料庫,包括新增資料、更新資料、刪除資料。
  那麼對這兩個件事情該怎麼做呢?
讀取資料時,我們是開啟一個連線,例項化一個資料介面卡然後填充資料集,關閉連線,即可。這裡要注意的是,由於資料集裡的表經常是資料庫裡多個資料表join的結果,所以你甭想讓操作器自動生成查詢語句,得你自己寫。
寫入資料的時候,就會有一些麻煩,但因為都是單表操作所以你可以不用自己寫SQL語句,讓操作器自己生成好了。
那麼一步步怎麼做呢?先開啟一個資料庫連線,再生成一個查詢字串,接著這兩個東東例項化一個資料介面卡,在生成一個CommandBuilder的例項並註冊為DataAdapter的偵聽器,接著事務。然後更新資料庫,最後關閉連線。事務不能更早配置,是因為配置的事務之後便不允許資料介面卡的命令為空。
思路有了,後面就很簡單了,我們只需要為每一種資料庫連線定義這些操作,然後根據實際情況就可以了。
當然我們不希望使用哪種資料庫的由呼叫它的作為引數傳入,定義在配置中似乎更好一些。
由於可能有多個資料庫,所以我們應當體現這種情況。比如我們可以定義預設資料庫連線為“DBCon”,資料庫A的連線為“ADBCon”。
由於要實現多張表的操作,所以我們要定義一個資料集表和表名的對映。

程式碼實現

  首先定義一個列舉,以指定可以支援哪些資料庫: ///   /// 資料庫型別列舉   ///   public enum DBType   {   ///   /// SQLServer   ///   SQLServer,   ///   /// Oracle   ///   Oracle,   ///   /// OleDB   ///   OleDb,   ///   /// Odbc   ///   Odbc
  }
 
  定義一個類來擴充套件DataTable:   ///   /// 用於更新資料庫的資料表、庫表名對   ///   public class DataTableExtend   {   ///   /// 資料表   ///   public System.Data.DataTable dataTable;     ///   /// 資料表對映到資料庫的表名   ///   public string dataTableName;     ///   /// 用於更新資料庫的資料表、庫表名對構造   ///   /// 用於更新資料庫的資料表   /// 資料表對映到資料庫的表名   public DataTableExtend(System.Data.DataTable myTable, string myTableName)   {   dataTable = myTable;   dataTableName = myTableName;   }
  }
 
  然後寫一個類來讀取配置檔案並獲取資料庫連線字串:   ///   /// DBSetting 的摘要說明。   ///   public class DBSetting   {   ///   /// 資料庫連線字串字尾   ///   public static string DBConnectionEnds   {   get   {   return "DBCon";   }   }     ///   /// 資料庫型別字尾   ///   public static string DBTypeEnds   {   get   {   return "DBType";   }
  } ///   /// 獲取指定資料庫的型別   ///   /// 指定的資料庫名   /// 指定資料庫的型別   public static DBType GetDBType(string dbName)   {   string dbType = null;   dbType = AppConfig.GetAppSetting(dbName + DBTypeEnds);   if (dbType.ToLower() == DBType.Oracle.ToString().ToLower())   {   return DBType.Oracle;   }   if (dbType.ToLower() == DBType.Odbc.ToString().ToLower())   {   return DBType.Odbc;   }   if (dbType.ToLower() == DBType.OleDb.ToString().ToLower())   {   return DBType.OleDb;   }   else   {   return DBType.SQLServer;   }
  } ///   /// 儲存指定資料庫的型別   ///   /// 指定資料庫的型別   /// 指定的資料庫名   public static void SaveDBType(DBType dbType,string dbName)   {   AppConfig.SaveAppSetting(dbName + DBTypeEnds,dbType.ToString());
  } ///   /// 獲取指定資料庫的連線字串   ///   /// 指定的資料庫名   /// 指定資料庫的連線字串   public static string GetDBConnectionString(string dbName)   {   return AppConfig.GetAppSetting(dbName + DBConnectionEnds);
  }
    ///   /// 儲存指定資料庫的連線字串   ///   /// 連線字串   /// 指定的資料庫名   public static void SaveDBConnectionString(string connectionString, string dbName)   {   AppConfig.SaveAppSetting(dbName + DBConnectionEnds,connectionString);
  }
}
 
接著為每一種資料庫寫一個類來執行針對該資料庫的操作,例如針對SQL Server: ///   /// 用於SQL資料來源操作的類   ///   public class SQLExec
  {   ///   /// 獲取資料庫連線,讀取由Storm.AppSetting的配置檔案中dbName + "DBCon"的設定(如針對資料庫Test的配置鍵是“TestDBCon”),若沒有,則丟擲異常   ///   /// 要獲取資料連線的資料庫名   /// 得到的資料庫連線   public static SqlConnection GetDBConnection(string dbName)   {   return new SqlConnection(DBSetting.GetDBConnectionString());
  }
  private void ModifyDataBase(DataTableExtend[] dts, string dbName)   {   //開啟連線   SqlConnection sqlCon = GetDBConnection(dbName);   sqlCon.Open();   //根據資料表的多少生成多個資料介面卡並分別生成SQL語句   int length = dts.Length;   SqlDataAdapter[] myDataAdapters = new SqlDataAdapter[length];   for (int i = 0; i < length; i++)   {   string Text = GetSelectCommand(dts[i].dataTableName);   myDataAdapters[i] = new SqlDataAdapter(selectText, sqlCon);   SqlCommandBuilder cb = new SqlCommandBuilder(myDataAdapters[i]);   myDataAdapters[i].InsertCommand = cb.GetInsertCommand();   myDataAdapters[i].UpdateCommand = cb.GetUpdateCommand();   myDataAdapters[i].DeleteCommand = cb.GetDeleteCommand();   }   //配置事務   SqlTransaction myTrans;   myTrans = sqlCon.BeginTransaction(IsolationLevel.RepeatableRead);   try   {   for (int i = 0; i < length; i++)   {   myDataAdapters[i].SelectCommand.Transaction = myTrans;   myDataAdapters[i].InsertCommand.Transaction = myTrans;   myDataAdapters[i].UpdateCommand.Transaction = myTrans;   myDataAdapters[i].DeleteCommand.Transaction = myTrans;   //更新資料庫   myDataAdapters[i].Update(dts[i].dataTable);   }   myTrans.Commit();   sqlCon.Close();   for(int i = 0; i < length ; i++)   {   dts[i].dataTable.AcceptChanges();   }   }   //如果失敗,則自動回滾   catch(Exception ee)   {   myTrans.Rollback();   sqlCon.Close();   for(int i = 0; i < length ; i++)   {   dts[i].dataTable.RejectChanges();   }   throw ee;   }
  }
  ///   /// 從資料庫中讀取資料   ///   /// 要承載資料的資料表   /// 查詢語句
  public void GetData(DataTable dt, string selectString, string dbName)
  { SqlDataAdapter myDataAdapter = new SqlDataAdapter(selectString,SQLConfig.GetDBConnection(dbName));
  myDataAdapter.Fill(dt);
  }
 
  //自動生成查詢語句 private static string GetSelectCommand(string dataTableName)   {   string strGet = "SELECT * FROM " +dataTableName;   return strGet;
  }
}
 
然後就是寫一個類來根據實際情況呼叫這些東東了: public class DatabaseExecute   {   private string dbName;   ///   /// 目標資料庫   ///   public string DBName   {   get{ return dbName; }   set{ dbName = value; }   }     ///   /// 生成DatabaseExecute的例項   ///   public DatabaseExecute()   {   dbName = null;   }     ///   /// 用指定的目標資料庫生成DatabaseModifier的例項   ///   ///   public DatabaseExecute(string dbName)   {   this.dbName = dbName;   }   ///   /// 從資料庫中讀取資料   ///   /// 要承載資料的資料表   /// 查詢語句   public void GetData(DataTable dt, string selectString)   {   //操作指定資料庫   if (DBName != null)   {   if (DBSetting.GetDBType(dbName) == DBType.SQLServer)   {   SQLExec Exec = new SQLExec();   mySQLExec. GetData(dt, selectString, DBName);   }   else if (DBSetting.GetDBType(dbName) == DBType.Odbc)   {   OdbcExec myOdbcExec = new OdbcExec();   myOdbcExec. GetData(dt, selectString, DBName);   }   else if (DBSetting.GetDBType(dbName) == DBType.OleDb)   {   OleDbExec myOleDbExec = new OleDbExec();   mySQLExec. GetData(dt, selectString, DBName);   }   else   {   OracleExec myOracleExec = new OracleExec();   myOracleExec. GetData(dt, selectString, DBName);   }   }   //操作預設資料庫   else   {   if (DBSetting.GetDBType(“”) == DBType.SQLServer)   {   SQLExec mySQLExec = new SQLExec();   mySQLExec. GetData(dt, selectString, “”);   }   else if (DBSetting.GetDBType(“”) == DBType.Odbc)   {   OdbcExec myOdbcExec = new OdbcExec();   myOdbcExec. GetData(dt, selectString, “”);   }   else if (DBSetting.GetDBType(dbName) == DBType.OleDb)   {   OleDbExec myOleDbExec = new OleDbExec();   mySQLExec. GetData(dt, selectString, “”);   }   else   {   OracleExec myOracleExec = new OracleExec();   myOracleExec. GetData(dt, selectString, “”);   }   }   }     ///   /// 根據資料表組更新資料庫   ///   /// 要更新的資料表組   public void ModifyDataBase(DataTableExtend[] dts)   {   //操作指定資料庫   if (dbName != null)   {   if (DBSetting.GetDBType(dbName) == DBType.SQLServer)   {   SQLExec mySQLExec = new SQLExec();   mySQLExec ModifyDataBase(dts,dbName);   }   else if (DBSetting.GetDBType(dbName) ==  DBType.Odbc)   {   OdbcExec mySQLExec = new OdbcExec();   myOdbcExec ModifyDataBase(dts,dbName);   }   else if (DBSetting.GetDBType(dbName) == DBType.OleDb)   {   OleDbExec mySQLExec = new OleDbExec();   myOleDbExec ModifyDataBase(dts,dbName);   }   else   {   OracleExec mySQLExec = new OracleExec();   myOracleExec ModifyDataBase(dts,dbName);   }   }   //操作預設資料庫   else   {   if (DBSetting.GetDBType(“”) == DBType.SQLServer)   {     SQLExec mySQLExec = new SQLExec();   mySQLExec ModifyDataBase(dts, “”);   }   else if (DBSetting.GetDBType(dbName) ==  DBType.Odbc)   {   OdbcExec mySQLExec = new OdbcExec();   myOdbcExec ModifyDataBase(dts, “”);   }   else if (DBSetting.GetDBType(dbName) == DBType.OleDb)   {   OleDbExec mySQLExec = new OleDbExec();   myOleDbExec ModifyDataBase(dts, “”);   }   else   {   OracleExec mySQLExec = new OracleExec();   myOracleExec ModifyDataBase(dts, “”);   }   }
}
 
這樣,在專案中只要引用這個DatabaseExecute類就可以了。
最後,要注意的幾點:
1.  對於多表操作而言,因為表間有關聯,所以操作的順序很重要,本構件操作的順序是從資料表陣列的前向後處理,請千萬注意表處理的順序!
2.  預設資料庫連線由配置檔案中“DBCon”的設定決定,非預設資料庫連線由配置檔案中“*DBCon”的設定決定,其中星號代表資料庫標識
3.  預設資料庫型別由配置檔案中“DBCon”的設定決定,非預設資料庫型別由配置檔案中“*DBCon”的設定決定,其中星號代表資料庫標識
4.  針對每一個資料庫都有兩個配置,分別是資料庫連線和資料庫型別。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10794571/viewspace-974705/,如需轉載,請註明出處,否則將追究法律責任。

用設計模式開發通用資料庫操作器 (轉)
請登入後發表評論 登入
全部評論

相關文章