名字起得有点夸张了,其实就是实现 基于 data access application block的dal基类和约束 首先repository部分没什么好描述的,如果有不了解的可以直接百度或者谷歌相关内容,直接上具体代码 注意此部分没有写批量查询的方法(比如findall,这跟后面的基类设定
        					名字起得有点夸张了,其实就是实现基于data access application block的dal基类和约束
首先repository部分没什么好描述的,如果有不了解的可以直接百度或者谷歌相关内容,直接上具体代码
注意此部分没有写批量查询的方法(比如findall,这跟后面的基类设定有关)
///     /// dataaccess repository    ///     ///     ///     public interface irepository    {        ///         /// 根据主键获取对应的实体对象        ///         ///         ///         t1 getentitybykey(t2 key);        ///         /// 单个新增        ///         ///         ///         bool insert(t1 entity);        ///         /// 单个编辑        ///         ///         ///         bool update(t1 entity);        ///         /// 单个删除        ///         ///         ///         bool delete(t2 key);    }
然后是dal抽象基类,该基类设计上实现读写分离,而且每个子类只应有一个数据库连接,这样做的隐藏目的是每个dal类都只应该执行自己最基本的功能:只关心数据库交互,不关心业务逻辑
    ///     /// dal基类,基于entlib,读写分离    ///     public abstract class dataaccessbase    {        private database _readdb;        private database _writedb;        ///         /// 要使用的读数据库配置节,如果配置为null或者空则会调用默认配置节        ///         protected abstract string readdbname { get; }        ///         /// 要使用的写数据库配置节,如果配置为null或者空则会调用默认配置节        ///         protected abstract string writedbname { get; }        ///         /// 读库        ///         protected database readdb        {            get            {                if (this._readdb == null)                {                    this._readdb = this.getdatabase(this._writedb, this.readdbname);                }                return this._readdb;            }        }        private database getdatabase(database db, string dbname)        {            if (this.readdbname == this.writedbname && db != null)            {                return db;            }            else            {                return this.createdatabase(dbname);            }        }        ///         /// 写库        ///         protected database writedb        {            get            {                if (this._writedb == null)                {                    this._writedb = this.getdatabase(this._readdb, this.writedbname);                }                return this._writedb;            }        }        private database createdatabase(string dbname)        {            databaseproviderfactory factory = new databaseproviderfactory();            if (string.isnullorwhitespace(dbname))            {                return factory.createdefault();            }            else            {                return factory.create(dbname);            }        }    }
最后就是irepository接口与dataaccessbase的组合实现singledataaccessbase,为什么不在dataaccessbase时就实现irepository呢?因为设计上dataaccessbase是可以同时运用于多表操作及单表操作的,多表操作时,irepository不存在任何意义,只有单表操作时,irepository才有意义,而singledataaccessbase就是单表dal基类    using system.collections.generic;    using system.linq;    using microsoft.practices.enterpriselibrary.data;    using system.data.common;    ///     /// 单表dataaccess基类,所有单表dataaccess应当继承此类,建议非共用部分同样实现接口    /// 多表但单数据库操作的dataaccess不能继承此类,而应继承dataaccessbase    ///     ///     ///     public abstract class singledataaccessbase : dataaccessbase, irepository        where t1 : new()    {        #region sqlstring        ///         /// getentitybykey方法对应的sql语句        ///         protected abstract string selectsql { get; }        ///         /// insert方法对应的sql语句        ///         protected abstract string insertsql { get; }        ///         /// update方法对应的sql语句        ///         protected abstract string updatesql { get; }        ///         /// delete方法对应的sql语句        ///         protected abstract string deletesql { get; }        #endregion        #region irepository 成员        ///         /// 根据主键获取对应的实体对象        ///         ///         ///         public virtual t1 getentitybykey(t2 key)        {            return this.readdb.executebysqlstring(this.selectsql, null, (irowmapper)null, this.getkeyparameters(key).toarray()).firstordefault();        }        ///         /// 单个新增,如果是自增主键,则需要override        ///         ///         ///         public virtual bool insert(t1 entity)        {            return this.writedb.executenonquerybysqlstring(this.insertsql, (cmd) => { this.setparametersbyentity(entity, cmd); }) > 0;        }        ///         /// 单个编辑        ///         ///         ///         public virtual bool update(t1 entity)        {            return this.writedb.executenonquerybysqlstring(this.updatesql, (cmd) => { this.setparametersbyentity(entity, cmd); }) > 0;        }        ///         /// 单个删除        ///         ///         ///         public virtual bool delete(t2 key)        {            return this.writedb.executenonquerybysqlstring(this.deletesql, (cmd) => { this.setparametersbykey(key, cmd); }) > 0;        }        #endregion        #region methods        ///         /// 通过entity填充dbparameter        ///         ///         ///         protected abstract void setparametersbyentity(t1 entity, dbcommand cmd);        ///         /// 通过key填充dbparameter        ///         ///         ///         protected virtual void setparametersbykey(t2 key, dbcommand cmd)        {            var paramters = this.getkeyparameters(key);            cmd.parameters.addrange(paramters.toarray());        }        ///         /// 通过协变的方式根据key获取对应的dbparameter        ///         ///         ///         protected abstract ienumerable getkeyparameters(t2 key);        #endregion    }
这里singledataaccessbase其实并不能算实现了irepository,只是进行了相关的约束规范而已,实际子类需要提供相应的sqlstring以及parameter实现(注意此处用到了前面博客中写的微软企业库扩展,具体见[entlib]微软企业库6 data access application block 扩展),因为data access application block其实并不是一个orm,如果采用这个类库,其实已经有比较大的概率可以确定系统对性能的要求较高,当然你也可以通过反射之类的实现真正的repository(前提是你的poco与关系型数据库中字段能对应上)
singledataaccessbase子类建议划分区域块,对应的代码写入对应区域,如
        #region connectionsetting        protected override string readdbname        {            get { throw new notimplementedexception(); }        }        protected override string writedbname        {            get { throw new notimplementedexception(); }        }        #endregion        #region sqlstring        protected override string selectsql        {            get { throw new notimplementedexception(); }        }        protected override string insertsql        {            get { throw new notimplementedexception(); }        }        protected override string updatesql        {            get { throw new notimplementedexception(); }        }        protected override string deletesql        {            get { throw new notimplementedexception(); }        }        #endregion        #region read        #endregion        #region write        #endregion        #region dbparameter        protected override void setparametersbyentity(t1 entity, dbcommand cmd)        {            throw new notimplementedexception();        }        protected override ienumerable getkeyparameters(t2 key)        {            throw new notimplementedexception();        }        #endregion
可能很多人觉得区分多表操作的dal和单表操作的dal没有必要或者没有意义,的确,在功能上,写在一个里面和写在多个里面没有区别,系统较小时还没有什么问题,如果系统较大,经由的开发人员较多时,很可能会出现某个开发人员想要用到某个表的某些字段,但因为系统较大又没有相关约束,导致该开发人员不知道去哪里找是否该方法已经存在,为了简易起见,最常见的做法是直接在自己需要的地方新写这部分代码,而最终的后果就是,代码分布越来越混乱,当表结构发生变化时,此部分尤其变成了灾难,因为如果不通过查表名,你根本无法预见到底哪些地方用到了这张表!而区分单表及多表操作,就是要解决这样的问题,当表结构发生变化时,也只需要找该表对应的单表dal以及以数据库对应的多表dal两个地方
最后吐槽下,企业库5真心伤不起,为了用dataaccess模块,连连千千添加了5个相关dll引用,真心怪不得人家不愿意用,还好6没了这个问题……
   
 
   