由於一個客戶朋友的需求,需要我的Winform開發框架支持國產達夢數據庫的操作,這個數據庫很早就聽過,但是真正一般項目用的很少,一般在一些特殊的項目可能需要用到。由於我的Winform開發框架,是基於Enterprise Library的數據訪問層的實現,因此增加一個數據庫的支持很容易,本文介紹如何在框架層面上支持這種神秘的國產數據庫-達夢數據庫。
1、達夢數據庫的簡單介紹
達夢數據庫管理系統是達夢公司推出的具有完全自主知識產權的高性能數據庫管理系統,簡稱DM。達夢數據庫管理系統的最新版本是7.0版本,簡稱DM7。DM7提供對SQL92的特性支持以及SQL99的核心級別支持;支持多種數據庫開發接口,包括OLE DB、ADO、ODBC、OCI、JDBC、Hibernate、PHP、PDO、DB Express以及.Net DataProvider等。
達夢數據庫可以在(http://www.dameng.com/)上下載試用,安裝好后提供很多管理工具,安裝后可以讓它創建一些實例數據庫,以方便我們了解數據庫的基本操作,本人對這款數據庫了解不多,不過它號稱支持SQL-92標准的,那么使用起來就不會有什么問題的,只是一些個性化的語法需要查詢即可。
達夢數據庫的分析器,可以在上面執行自己的一些語句,注意它的數據庫表必須帶上一個模式前綴,類似SqlServer的dbo,不過這個是必須的。
2、基於Enterprise Library的Winform開發框架的架構支持處理
我的這款基於Enterprise Library的開發框架,底層使用了微軟的數據訪問組件Enterprise Library,以適應多種數據庫類型的操作,它的分層如下所示,每個DAL層(如DALSQL、DALOracle等)都提供了對應數據庫的實現,界面層一下的分層圖如下所示。
如果增加多一種數據庫,那么我們增加多一個Enterprise Library的組件擴展類,並在業務數據模塊里面增加對應的DAL層即可。
對於具體的DALSQL這樣的數據實現層,我們不需要把數據訪問的處理操作在全部的類里面實現一遍,我們可以通過抽象類的方式,把常規的數據庫處理操作抽象到基類上面,如下所示。
這樣在BaseDALSQL層(SqlServer數據庫的個性化實現部分),只需要實現部分功能即可,我們把大多數的數據庫操作,放到最頂級的數據庫訪問基類AbstractBaseDAL類上,從而是我們能夠盡可能減少增加不同數據庫類型,需要改寫代碼的數量。
最終我們增量增加一個數據訪問層就可以實現了另外一種數據庫(達夢數據庫)的實現了,具體的架構設計圖如下所示。
3、具體接入測試案例代碼
上面小節,我們論證了框架的可擴展性,並且理論上已經具備支持達夢數據庫的擴張了,本小節介紹如何具體實現達夢數據庫的底層接入操作,並編寫一個簡單的測試例子進行測試,印證我們的實現思路。
我們知道,Enterprise Library實現其他數據庫的支持,需要增加一個組件擴展類,如EntLibContrib.Data.SQLite是用來支持SQLite數據庫的,EntLibContrib.Data.MySql是用來支持Mysql的,這個擴展類的內容也不多,主要是用來解析如下的配置文件的.
以便能夠和Enterprise Library的對象進行無縫的整合,那么我們可以參考MySql數據庫的擴展類EntLibContrib.Data.MySql的做法,來創建一個基於國產達夢數據庫的Enterprise Library擴展類,大概項目代碼如下所示。
這樣我們就可以增加配置文件如下所示,它就能正常的解析並處理了。
下面我們來編寫測試的代碼來印證我們的擴展類,實現Winform開發框架支持國產達夢數據庫的擴展操作。
我們創建一個數據庫通用操作的輔助類來進行講解,代碼如下所示。
/// <summary> /// 基於Enterprise Library類庫的數據訪問測試 /// </summary> public class EntLibDmHelper { public EntLibDmHelper() { } /// <summary> /// 執行SQL查詢語句,返回查詢結果的所有記錄的第一個字段,用逗號分隔。 /// </summary> /// <param name="sql">SQL語句</param> /// <returns> /// 返回查詢結果的所有記錄的第一個字段,用逗號分隔。 /// </returns> public string SqlValueList(string sql) { Database db = DatabaseFactory.CreateDatabase(); DbCommand command = db.GetSqlStringCommand(sql); StringBuilder result = new StringBuilder(); using (IDataReader dr = db.ExecuteReader(command)) { while (dr.Read()) { result.AppendFormat("{0},", dr[0].ToString()); } } string strResult = result.ToString().Trim(','); return strResult; } /// <summary> /// 執行SQL查詢語句,返回所有記錄的DataTable集合。 /// </summary> /// <param name="sql">SQL查詢語句</param> /// <returns></returns> public DataTable SqlTable(string sql) { DataSet ds = new DataSet(); Database db = DatabaseFactory.CreateDatabase(); DbCommand command = db.GetSqlStringCommand(sql); return db.ExecuteDataSet(command).Tables[0]; } }
注意,上面的代碼沒有用到達夢的具體對象,而是使用了Enterprise Library的Database等對象來操作,這樣也就是非常方便我們進行接口的抽象處理,可以把更多的功能放到數據庫訪問抽象類里面了。
如果是利用達夢的.NET Provider的對象處理數據庫,那么具體的代碼應該是這樣的。
/// <summary> /// 執行SQL查詢語句,返回查詢結果的所有記錄的第一個字段,用逗號分隔。 /// </summary> /// <param name="sql">SQL語句</param> /// <returns> /// 返回查詢結果的所有記錄的第一個字段,用逗號分隔。 /// </returns> public string SqlValueList(string sql) { DmConnection connection = new DmConnection(ConnectionString); DmCommand cmd = new DmCommand(sql, connection); connection.Open(); StringBuilder result = new StringBuilder(); using (DmDataReader dr = cmd.ExecuteReader()) { while (dr.Read()) { result.AppendFormat("{0},", dr[0].ToString()); } } string strResult = result.ToString().Trim(','); return strResult; } /// <summary> /// 執行SQL查詢語句,返回所有記錄的DataTable集合。 /// </summary> /// <param name="sql">SQL查詢語句</param> /// <returns></returns> public DataTable SqlTable(string sql) { DataSet ds = new DataSet(); DmDataAdapter adpater = new DmDataAdapter(sql, ConnectionString); adpater.Fill(ds); return ds.Tables[0]; }
為了方便測試,我編寫一個簡單的查詢例子來進行介紹,如下代碼所示,這里我們主要利用了EntLibDmHelper這個輔助類對象,也就是基於Enterprise Library的擴展的處理操作。
private void btnSearch_Click(object sender, EventArgs e) { BindData(); } private void BindData() { string condition = "1=1 "; if (this.txtAuthor.Text.Length > 0) { condition += string.Format("AND Author like '%{0}%' ", this.txtAuthor.Text); } if (this.txtName.Text.Length > 0) { condition += string.Format("AND Name like '%{0}%' ", this.txtName.Text); } if (this.txtPublisher.Text.Length > 0) { condition += string.Format("AND Publisher like '%{0}%' ", this.txtPublisher.Text); } string sql = "Select * from PRODUCTION.Product Where " + condition; EntLibDmHelper helper = new EntLibDmHelper(); //DMHelper helper = new DMHelper(); DataTable dt = helper.SqlTable(sql); this.dataGridView1.DataSource = dt; sql = "Select count(*) from PRODUCTION.Product Where " + condition; string totalCount = helper.SqlValueList(sql); this.lblCount.Text = string.Format("共有數據:{0}條", totalCount); }
最后例子運行的界面效果如下所示。
基本上印證了我們對框架的整合,實現了支持國產達夢數據庫的擴展操作。剩下的就是我們模仿着把BaseDALSQL這樣的基類,為達夢數據庫增加一個個性化的數據庫處理接口,就可以實現整體性框架的支持了。對於各個模塊 的數據訪問,我們需要增加一個DALDM這樣的實現層,基類指向BaseDALDM這樣就可以了。