在很多應用系統(tǒng)里面氢哮,雖然一般采用一種數據庫運行葛圃,但是由于各種情況的需要默垄,可能業(yè)務系統(tǒng)會部署在不同類型的數據庫上此虑,如果開發(fā)的系統(tǒng)能夠很方便支持多種數據庫的切換,那可以為我們減少很多煩惱口锭,同時提高系統(tǒng)的適應性和強壯型寡壮。還有一種情況,由于業(yè)務數據庫的不斷膨脹或者方便數據庫的切割隔離,有時候也會把不同的業(yè)務數據庫進行分拆况既,如權限提供數據庫这溅,客戶關系管理數據庫,工作流程數據庫棒仍,企業(yè)營運數據庫等等悲靴,因此在一個系統(tǒng)里面,同時使用2個或者以上的數據庫的情況也是有的莫其。
在我較早期的一篇隨筆《Winform開發(fā)框架中實現多種數據庫類型切換以及分拆數據庫的支持》里面癞尚,介紹了框架如何在一個項目里支持多個數據庫的拆分處理。一般情況下乱陡,我們都是在一個數據庫類型的情況下浇揩,分拆多個數據庫,但是也有變態(tài)的需求例外憨颠,如我們可能把一些常規(guī)的數據庫存儲在本地SQLite數據庫里面胳徽,其他的一些數據放在局域網其他類型數據庫(如SQLServer)里面;那么這種同一時刻支持多種數據庫類型爽彤,并且給用戶創(chuàng)建BLL層類的時候养盗,動態(tài)指定數據庫是否可以實現的呢?
當然可以适篙,我們在上面的基礎上稍微調整一下創(chuàng)建方法即可往核。
1、同時支持多種類型數據庫處理并存
之前介紹了嚷节,需要分拆數據庫的話聂儒,我們需要在數據訪問基類AbstractBaseDAL里面,添加一個SetConfigName的方法硫痰,用來指定具體的數據庫配置項目衩婚,如下所示。
/// <summary>
/// 數據訪問層的超級基類碍论,所有數據庫的數據訪問基類都繼承自這個超級基類谅猾,包括Oracle、SqlServer鳍悠、Sqlite税娜、MySql、Access等
/// </summary>
public abstract class AbstractBaseDAL<T> where T : BaseEntity, new()
{
/// <summary>
/// 設置數據庫配置項名稱
/// </summary>
/// <param name="dbConfigName">數據庫配置項名稱</param>
public virtual void SetDbConfigName(string dbConfigName)
{
this.dbConfigName = dbConfigName;
}
....................
}
那么我們這次只需要在這個基礎上調整一下就可以實現同一時刻變換不同數據庫支持的了藏研,由于在框架里面敬矩,我們一般已經實現了多種數據庫訪問的邏輯(如下所示),因此切換起來訪問肯定也是沒問題的(保證有數據庫即可)蠢挡。
方法就是在BLL層里面添加一個公開方法弧岳,可以設置配置項和數據庫類型的函數凳忙,如下所示。
/// <summary>
/// 根據參數信息禽炬,重新初始化數據訪問層(例:可以指定不同的數據訪問層)
/// </summary>
/// <param name="dbConfigName">數據庫配置項名稱</param>
/// <param name="componentDbType">數據庫類型涧卵,默認從ComponentDbType中讀取,如果dbConfigName指定不同類型的數據庫連接腹尖,需要指定componentDbType柳恐。</param>
public void SetConfigName(string dbConfigName, string componentDbType = null)
{
//componentDbType = null時,從配置項取ComponentDbType的值
string dbType = componentDbType;
if (string.IsNullOrEmpty(componentDbType))
{
AppConfig config = new AppConfig();
dbType = config.AppConfigGet("ComponentDbType");
}
string DALPrefix = GetDALPrefix(dbType);
this.dalName = bllFullName.Replace(bllPrefix, DALPrefix);//替換中級的BLL.為DAL.热幔,就是DAL類的全名
baseDal = Reflect<IBaseDAL<T>>.Create(this.dalName, dalAssemblyName);//構造對應的DAL數據訪問層的對象類
if (!string.IsNullOrEmpty(dbConfigName))
{
baseDal.SetDbConfigName(dbConfigName); //設置數據庫配置項名稱
}
}
這樣我們除了可以設置EnterpriseLibrary的配置項外乐设,還可以指定這個數據庫的類型,不需要全部使用統(tǒng)一的ComponentDbType的值绎巨。
如下代碼處理近尚,我們就可以在訪問其他數據庫的時候,切換這個BLL層的對象為其他類型的數據庫(SQLite)场勤,這樣不管其他類如何變化戈锻,這個Province的數據訪問的是SQLite數據庫里面的數據。
BLLFactory<Province>.Instance.SetConfig("sqlite", "sqlite");
2却嗡、支持多數據庫操作的基類CommonDAL舶沛,實現不同數據庫訪問
有時候嘹承,我們在一個比較小的應用程序里面窗价,想靈活對數據庫表進行一些簡單的處理操作,不想使用代碼生成工具生成整個架構的代碼叹卷,那么這個時候撼港,這個CommonDAL就派上用場了,這個可以快速訪問數據庫的表骤竹,它的定義如下所示帝牡。
這個類的幾個構造函數如下所示,參數分別為表名蒙揣,主鍵字段靶溜,數據庫類型。
/// <summary>
/// 默認構造函數
/// </summary>
public CommonDAL()
{
}
/// <summary>
/// 指定表名以及主鍵,對基類進構造
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="primaryKey">表主鍵</param>
/// <param name="dbType">數據庫類型懒震,如果為空從配置文件里面獲取ComponentDbType的鍵值</param>
public CommonDAL(string tableName) : this(tableName, null, null)
{
}
/// <summary>
/// 指定表名以及主鍵,對基類進構造
/// </summary>
/// <param name="tableName">表名</param>
/// <param name="primaryKey">表主鍵</param>
/// <param name="dbType">數據庫類型罩息,如果為空從配置文件里面獲取ComponentDbType的鍵值</param>
public CommonDAL(string tableName, string primaryKey, string dbType = null)
: this()
{
}
這個就是一個精簡版本的AbstractBaseDAL基類,提供了我們能夠使用的多數數據庫操作方法个扰。
例如我在一個驗證視圖及其格式的例子程序里面瓷炮,就使用了這個類來實現快速的數據庫操作處理。
/// <summary>
/// 判斷視圖名稱是否存在的任務
/// </summary>
public class ViewNameExistJob : IExecuteJob
{
public bool Execute()
{
List<string> list = DataHelper.GetViewList();
bool allSuccess = true;
foreach (string view in list)
{
CommonDb dal = new CommonDb(view, "F_Guid");
try
{
DataTable dt = dal.GetReaderSchema(view);
}
catch (Exception ex)
{
allSuccess = false;
LogTextHelper.Error(string.Format("視圖:{0}不存在递宅。{1}", view, ex.Message));
}
}
if (allSuccess)
{
LogTextHelper.Info("視圖全部存在娘香。");
}
return allSuccess;
}
}
或者其他數據庫訪問處理苍狰。
CommonDb dal = new CommonDb(view, "F_Guid");
try
{
int count = dal.GetRecordCount();
if (count == 0)
{
LogTextHelper.Info(string.Format("視圖【{0}】數據為空,請檢查烘绽!", view));
allSuccess = false;
}
}
catch (Exception ex)
{
allSuccess = false;
LogTextHelper.Error(string.Format("視圖:【{0}】不存在淋昭。{1}", view, ex.Message));
}
這樣也可以實現多數據庫的隨便切換,不過這個是用于簡易的數據庫訪問安接,對于需要多種業(yè)務封裝的處理類响牛,我們還是使用常規(guī)的框架分層模式來實現數據的處理操作。