Winform开发框架中实现多种数据库类型切换以及分拆数据库的支持

在很多应用系统里面,虽然一般采用一种数据库运行,但是由于各种情况的需要,可能业务系统会部署在不同类型的数据库上,如果开发的系统能够很方便支持多种数据库的切换,那可以为我们减少很多烦恼,同时提高系统的适应性和强壮型。还有一种情况,由于业务数据库的不断膨胀或者方便数据库的切割隔离,有时候也会把不同的业务数据库进行分拆,如权限提供数据库,客户关系管理数据库,工作流程数据库,企业营运数据库等等,因此在一个系统里面,同时使用2个或者以上的数据库的情况也是有的。针对这两种情况,本文介绍在我的Winform开发框架(也使用我的其他框架),如何具体处理这两个问题的。

在我的各种开发框架里面,底层都是采用同一种数据库的访问方式,就是采用了Enterprise Library的数据库访问模块,这个是微软开源的企业应用模块,里面各种应用模块,都堪称是开发的最佳实践。当然利用里面的数据库访问模块,是很广泛的,这个数据库访问模块,可以通过配置的方式支持多种数据库的变化。因此整合到我的Winform开发框架里面,也很容易实现这种多数据库的方式处理。

Winform开发框架,常见的分层模式,可以分为UI层、BLL层、DAL层、IDAL层、Entity层、公用类库层等等,B/S的Web开发框架也是提供类似的架构模式,它们只是Web界面层有所不同,这样就给我们提供了一个统一性的开发模式,使得开发起来更加高效,统一性更好。框架界面层以下的架构设计图如下所示。

1、支持多数据库的设置

1)数据库访问基类的了解

为了介绍支持多种数据库的模式,我们需要先来了解下整个框架的层次结构。

AbstractBaseDAL是抽象了所有数据库实现的超级基类。

BaseDALSQL是针对SqlServer数据库部分调整基类(很小的调整)。

BaseDALSQLite是针对Sqlite数据库的部分调整基类(很小的调整)。

BaseDALMySql是针对MySqlite数据库的部分调整基类(很小的调整)。

BaseDALAccess是针对Access数据库的部分调整基类(很小的调整)。

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"/>

2、支持分拆不同数据库的设置

上面介绍的方式,一次性只能访问一个数据库,因此默认在代码构造数据库访问对象的时候,是通过下面的代码进行的。

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

2、在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;
        }
....................
}

3、在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); //设置数据库配置项名称
        }

4、在具体BLL层的业务类进行初始化处理。

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

这样设置后,我们具体调用的代码不变,但是指定业务的数据库访问已经使用了特定的配置项名称了,如果配置项不存在,那么还是会获取默认的配置项进行处理了。

通过这样的实现步骤,我们就能实现在一个业务系统里面,分拆不同的数据库,进行统一管理,而且又不会增加额外的调用难度,对于我们很多业务表,这种框架的处理方式 ,应该是不错的。

本文转自博客园伍华聪的博客,原文链接:Winform开发框架中实现多种数据库类型切换以及分拆数据库的支持,如需转载请自行联系原博主。

时间: 2024-12-11 16:51:34

Winform开发框架中实现多种数据库类型切换以及分拆数据库的支持的相关文章

Winform开发框架中实现同时兼容多种数据库类型处理

在很多应用系统里面,虽然一般采用一种数据库运行,但是由于各种情况的需要,可能业务系统会部署在不同类型的数据库上,如果开发的系统能够很方便支持多种数据库的切换,那可以为我们减少很多烦恼,同时提高系统的适应性和强壮型.还有一种情况,由于业务数据库的不断膨胀或者方便数据库的切割隔离,有时候也会把不同的业务数据库进行分拆,如权限提供数据库,客户关系管理数据库,工作流程数据库,企业营运数据库等等,因此在一个系统里面,同时使用2个或者以上的数据库的情况也是有的. 在我较早期的一篇随笔<Winform开发框架

在Winform开发框架中实现对数据库的加密支持

在很多情况下,我们需要对数据库进行加密,特别是Access数据库.Sqlite数据库,这些直接部署在客户端的数据,因为数据也是客户的资产,数据库总是存在很多相关的秘密或者重要的业务数据,所以一般来说,数据库是比较敏感的.由于我的Winform开发框架数据库访问模块中采用了EnterpriseLibrary模块,因此其实也可以使用其中的Crytography Application Block进行加解密处理. 由于不想引入太多这些额外的模块,或者为了简化客户端的配置考虑,直接在Enterprise

Winform开发框架中的内容及文档管理模块功能介绍

在开发项目的时候,我们有一些场景需要编辑一些HTML文档,作为内容发布系统的一部分,有时候也需要对一些文档如WORD文档进行编辑管理,这样需要我们对这些内容及文档进行合适的管理.本文主要介绍在WInform项目中利用ZetaHtmlEditControl进行HTML内容管理,以及利用TX TextControl控件进行WORD文档管理,这两方面都是我们一般进行内容和文档管理所必须的. 1.内容及文档管理模块功能介绍 整个模块,支持WInform框架和混合式开发框架两种模式,都是基于WInform

Winform开发框架中工作流模块的业务表单开发

在我们开发工作流的时候,往往需要设计到具体业务表单信息的编辑,有些是采用动态编辑的,有些则是在开发过程中处理的,各有各的优点,动态编辑的则方便维护各种各样的表单,但是数据的绑定及处理则比较麻烦,而自定义开发的,则数据弹性很大,方便修改调整.本篇随笔基于表单的开发设计过程,介绍在工作流中如何新增一个业务表单,以便快速的实现审批业务的上线处理. 1.业务表单的基类继承 首先我们来了解一下业务表单的对应关系,一般创建一个业务流程处理,都需要有一个具体的创建业务表单的界面,以及一个查看处理表单的界面.

在Winform开发框架中,利用DevExpress控件实现数据的快速录入和选择

在实际的项目开发过程中,有好的控件或者功能模块,我都是想办法尽可能集成到我的WInform开发框架中,这样后面开发项目起来,就可以节省很多研究时间,并能重复使用,非常高效方便.在我很早之前的一篇博客<在GridControl控件中使用SearchLookUpEdit构建数据快速输入>就曾经介绍,如何在列表控件中实现数据的快速录入,本文介绍另外一种方式,通过文本输入框的输入选择,可以实现数据的快速录入,原理和之前一篇差不多,不过这次利用DevExpress控件的GridLookupEdit控件封

ASP.NET中如何将decimal 类型的数据 存在 ORACLE数据库

问题描述 ASP.NET中如何将decimal类型的数据存在ORACLE数据库 解决方案 解决方案二:Oracle数据库中Number类型的参数的值可以用.NETdecimal或System.Data.OracleClient.OracleNumber类型指定:Integer类型的参数的值可以用.NETint或OracleNumber类型指定解决方案三:NUMBER12,7

Winform开发框架中的综合案例Demo

在实际的系统开发中,我们往往需要一些简单的的案例代码,基于此目的我把Winform开发框架中各种闪光点和不错的功能,有些是我们对功能模块的简单封装,而有些则是引入了一些应用广泛的开源组件进行集成使用,因此把它们做了一个Demo进行展示,以方便我们随时了解和参考,并能够快速应用相应的场景到具体的项目中. 1.闪屏展示界面及主体界面 在很多系统里面,提供一个设计不错的图片作为程序界面展示的效果是挺不错的,这个小程序也不例外,基本上整合了一些WInform界面常用的各种功能. 而整个案例的界面的界面以

Winform开发框架中工作流模块之申请单草稿处理

在我们开发工作流模块的时候,有时候填写申请单过程中,暂时不想提交审批,那么可以暂存为草稿,以供下次继续填写或者提交处理,那么这个草稿的功能是比较实用的,否则对于一些填写内容比较多的申请单,每次要重填写很多数据,那会被用户骂的,从用户的角度上来讲,提供草稿保存的功能是比较友好的.本篇随笔介绍在工作流模块中使用一种通用的存储方式来存储及显示申请单草稿的信息. 1.申请单填写 在我们提交申请前,我们一般是需要填写一些相关的资料,如下界面所示. 这个表单记录的信息不多,不过提供存为草稿的功能也是要的,我

Winform开发框架中工作流模块之审批会签操作

在前面介绍了框架中工作流的几个开发过程,本篇随笔重点介绍一下日常审批环节中的具体处理过程,从开始创建表单,以及各个审批.会签过程的流转过程,希望大家对其中流程的处理有一个大概的印象. 1.请假申请表单 这里介绍的具体功能,是在业务表单已经完成好,具体的使用过程,我们以请假申请单为例,在我们创建对应的流程步骤如下所示后, 我们就可以开始创建具体的业务审批流程了,在业务受理列表里面选择对应的请假申请,弹出相应的创建业务流程表单窗体. 单击[发送]按钮,会要求选择下一步的审批人,如下所示.  这样对应