Winform開發框架中實現多種數據庫類型切換以及分拆數據庫的支持

在不少應用系統裏面,雖然通常採用一種數據庫運行,可是因爲各類狀況的須要,可能業務系統會部署在不一樣類型的數據庫上,若是開發的系統可以很方便支持多種數據庫的切換,那能夠爲咱們減小不少煩惱,同時提升系統的適應性和強壯型。還有一種狀況,因爲業務數據庫的不斷膨脹或者方便數據庫的切割隔離,有時候也會把不一樣的業務數據庫進行分拆,如權限提供數據庫,客戶關係管理數據庫,工做流程數據庫,企業營運數據庫等等,所以在一個系統裏面,同時使用2個或者以上的數據庫的狀況也是有的。針對這兩種狀況,本文介紹在個人Winform開發框架(也使用個人其餘框架),如何具體處理這兩個問題的。mysql

在個人各類開發框架裏面,底層都是採用同一種數據庫的訪問方式,就是採用了Enterprise Library的數據庫訪問模塊,這個是微軟開源的企業應用模塊,裏面各類應用模塊,都堪稱是開發的最佳實踐。固然利用裏面的數據庫訪問模塊,是很普遍的,這個數據庫訪問模塊,能夠經過配置的方式支持多種數據庫的變化。所以整合到個人Winform開發框架裏面,也很容易實現這種多數據庫的方式處理。sql

Winform開發框架,常見的分層模式,能夠分爲UI層、BLL層、DAL層、IDAL層、Entity層、公用類庫層等等,B/S的Web開發框架也是提供相似的架構模式,它們只是Web界面層有所不一樣,這樣就給咱們提供了一個統一性的開發模式,使得開發起來更加高效,統一性更好。框架界面層如下的架構設計圖以下所示。數據庫

一、支持多數據庫的設置

1)數據庫訪問基類的瞭解架構

爲了介紹支持多種數據庫的模式,咱們須要先來了解下整個框架的層次結構。oracle

AbstractBaseDAL是抽象了全部數據庫實現的超級基類。app

BaseDALSQL是針對SqlServer數據庫部分調整基類(很小的調整)。框架

BaseDALSQLite是針對Sqlite數據庫的部分調整基類(很小的調整)。ide

BaseDALMySql是針對MySqlite數據庫的部分調整基類(很小的調整)。函數

BaseDALAccess是針對Access數據庫的部分調整基類(很小的調整)。sqlserver

IBaseDAL是全部基礎數據庫訪問類的接口。

數據訪問接口實現層(如Customer)和接口定義層(ICustomer)同樣,都有一個基類,如基於SqlServer實現的基類爲BaseDALSQL,這個基於SqlServer的數據訪問基類,它也是繼承自一個超級基類(大多數的實如今這裏)AbstractBaseDAL。他們之間的繼承關係以下所示

而咱們剛纔在項目工程的圖裏面看到,BaseDALSQL、IBaseDAL、AbstractBaseDAL這些類庫因爲具備很大的通用性,爲了減小在不一樣的項目中進行復制致使維護問題,所以咱們所有把這些常用到的基類或者接口,抽取到一個獨立的類庫裏面,爲了和普通的DotNET公用類庫命名進行區分(WHC.Framework.Commons),咱們把它命名爲WHC.Framework.ControlUtil。

2)多數據庫的代碼實現

爲了實現多數據庫的支持,咱們須要在配置文件裏面讀取相關的配置,看具體是構造那種該數據庫的,而後進行初始化不一樣的程序集類,從而實現調用不一樣數據庫類型的數據庫訪問類。

在BaseBLL的Init函數裏面的實現代碼以下所示。

            #region 根據不一樣的數據庫類型,構造相應的DAL層
            AppConfig config = new AppConfig();
            string dbType = config.AppConfigGet("ComponentDbType");
            if (string.IsNullOrEmpty(dbType))
            {
                dbType = "sqlserver";
            }
            dbType = dbType.ToLower();

            string DALPrefix = "";
            if (dbType == "sqlserver")
            {
                DALPrefix = "DALSQL.";
            }
            else if (dbType == "access")
            {
                DALPrefix = "DALAccess.";
            }
            else if (dbType == "oracle")
            {
                DALPrefix = "DALOracle.";
            }
            else if (dbType == "sqlite")
            {
                DALPrefix = "DALSQLite.";
            }
            else if (dbType == "mysql")
            {
                DALPrefix = "DALMySql.";
            }
            #endregion

            this.dalName = bllFullName.Replace(bllPrefix, DALPrefix);//替換中級的BLL.爲DAL.,就是DAL類的全名
            baseDal = Reflect<IBaseDAL<T>>.Create(this.dalName, dalAssemblyName);//構造對應的DAL數據訪問層的對象類

在具體的業務對象的調用的時候,咱們不知道它具體是調用哪一個數據庫的處理類進行處理的,只須要調用它的基礎接口就能夠了,以下是界面層的部分調用代碼。

            //刪除關聯的附件
            if (!string.IsNullOrEmpty(ids))
            {
                string[] idArray = ids.Split(',');
                foreach (string id in idArray)
                {
                    InformationInfo info = BLLFactory<Information>.FindByID(id);
                    if (info != null && !string.IsNullOrEmpty(info.Attachment_GUID))
                    {
                        BLLFactory<FileUpload>.Instance.DeleteByAttachGUID(info.Attachment_GUID);
                    }
                }
            }

在具體的配置文件裏面,咱們就能夠根據須要配置好相關的數據庫了。

根據Enterprise Library的配置,咱們只要制定了<dataConfiguration defaultDatabase="sqlserver">,那麼就會獲取sqlServer的節點,而代碼經過解析ComponentDbType配置項,就能夠構造對應的數據庫訪問對象了。二者合一就能夠正確獲取處處理對象,併成功處理數據庫的訪問。

<configuration>
  <configSections>
    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data"/>
  </configSections>
  <connectionStrings>
    <add name="sqlserver" providerName="System.Data.SqlClient" connectionString="Persist Security Info=False;Data Source=(local);Initial Catalog=MVCWebMis;Integrated Security=SSPI"/>
    <add name="access" providerName="System.Data.OleDb" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\ComponentData.mdb;User ID=Admin;Jet OLEDB:Database Password=;"/>
    <add name="sqlite" providerName="System.Data.SQLite" connectionString="Data Source=|DataDirectory|\ComponentData.db;Version=3;"/>
    <add name="oracle" providerName="System.Data.OracleClient" connectionString="Data Source=whcdb;User ID=whc;Password=whc"/>
  </connectionStrings>
  <dataConfiguration defaultDatabase="sqlserver">
    <providerMappings>
      <add databaseType="EntLibContrib.Data.SQLite.SQLiteDatabase, EntLibContrib.Data.SqLite" name="System.Data.SQLite"/>
    </providerMappings>
  </dataConfiguration>
  
  <appSettings>
    <!--組件的數據庫類型:access、sqlserver、sqlite等-->
    <add key="ComponentDbType" value="sqlserver"/>

 

二、支持分拆不一樣數據庫的設置

上面介紹的方式,一次性只能訪問一個數據庫,所以默認在代碼構造數據庫訪問對象的時候,是經過下面的代碼進行的。

Database db = DatabaseFactory.CreateDatabase();

這樣每次只會獲取defaultDatabase設置的數據庫進行構造,若是咱們在一個系統裏面,同時支持多個數據庫的訪問,那麼咱們應該如何處理呢。

在框架的基類AbstractBaseDAL裏面,咱們對構造數據庫的代碼進行了封裝。

        /// <summary>
        /// 根據配置數據庫配置名稱生成Database對象
        /// </summary>
        /// <returns></returns>
        protected virtual Database CreateDatabase()
        {
            Database db = null;
            if (string.IsNullOrEmpty(dbConfigName))
            {
                db = DatabaseFactory.CreateDatabase();
            }
            else
            {
                db = DatabaseFactory.CreateDatabase(dbConfigName);
            }
            return db;
        }

而每一個DAL層都會繼承自AbstractBaseDAL,這樣也就能夠經過在DAL層指定dbConfigName進行使用不一樣的數據庫的了。

可是這樣問題出現了,假如咱們有5個不一樣類型(SqlServer、Oracle、Mysql、Access、Sqlite)的數據庫的DAL層,那麼每一個DAL層的實現類都要寫一些代碼,這樣挺不方便,那麼是否能夠把它抽象到BLL層,這樣只寫一次配置就能夠了,這個思路很好,咱們具體來看看如何實現。

1)在IBaseDAL層定義接口

    /// <summary>
    /// 數據訪問層的接口
    /// </summary>
    public interface IBaseDAL<T> where T : BaseEntity
    {
        /// <summary>
        /// 設置數據庫配置項名稱
        /// </summary>
        /// <param name="dbConfigName">數據庫配置項名稱</param>
        void SetDbConfigName(string dbConfigName);
............. }

二、在AbstractBaseDAL添加默認實現代碼

    /// <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;
        }
.................... }

三、在BaseBLL裏面的Init函數進行調用設置處理

        /// <summary>
        /// 參數賦值後,初始化相關對象
        /// </summary>
        /// <param name="bllFullName">BLL業務類的全名(子類必須實現),子類構造函數傳入this.GetType().FullName</param>
        /// <param name="dalAssemblyName">數據訪問層程序集的清單文件的文件名,不包括其擴展名。設置爲NULL或默認爲Assembly.GetExecutingAssembly().GetName().Name</param>
        /// <param name="bllPrefix">BLL命名空間的前綴(BLL.)</param>
        /// <param name="dbConfigName">數據庫配置項名稱</param>
        protected void Init(string bllFullName, string dalAssemblyName = null, string bllPrefix = "BLL.")
        {
            .............
            baseDal.SetDbConfigName(dbConfigName); //設置數據庫配置項名稱
        }

四、在具體BLL層的業務類進行初始化處理。

    /// <summary>
    /// 政策法規公告動態
    /// </summary>
    public class Information : BaseBLL<InformationInfo>
    {
        public Information() : base()
        {
            base.Init(this.GetType().FullName, System.Reflection.Assembly.GetExecutingAssembly().GetName().Name, "BLL.", "annotherConfig" );
        }

這樣設置後,咱們具體調用的代碼不變,可是指定業務的數據庫訪問已經使用了特定的配置項名稱了,若是配置項不存在,那麼仍是會獲取默認的配置項進行處理了。

經過這樣的實現步驟,咱們就能實如今一個業務系統裏面,分拆不一樣的數據庫,進行統一管理,並且又不會增長額外的調用難度,對於咱們不少業務表,這種框架的處理方式 ,應該是不錯的。

相關文章
相關標籤/搜索