zoukankan      html  css  js  c++  java
  • Unit Of Work--工作单元(二)

    回顾

      上一篇我们根据工作单元的原理基于ADO.NET进行了简单的实现,但是当项目需求发生变化的时候,比如需要引入ORM框架又要兼容当前ADO.NET实现的方式时,先前的实现就无法满足这个需求了。

      话就不多说了,我们就跟据当前的需求变化来重构工作单元吧。

    重构UnitOfWork

      首先我们看看原先实现的工作单元提取出来的接口,代码如下:

    public interface IUnitOfWork
    {
        void RegisterAdd(string sql, params IDataParameter[] parameters);                             
        void RegisterSave(string sql, params IDataParameter[] parameters);                           
        void RegisterRemove(string sql, params IDataParameter[] parameters);                          
        void Comit();
    }

      由于需求需要兼容ORM和ADO.NET方式,而以上的接口仅仅支持ADO.NET的方式,因此接口需要改变,例如:

    //其他代码省略
    void RegisterAdd(object entity);
    

      观察以上的修改会发现如果要满足需求,则需要判断是ADO.NET或者是ORM的操作,那么就有了两种不同的职责,这显然是不合理的,但是如果我们将ADO.NET和ORM还是让对应的数据层类去实现的话,就符合单一责任了,于是经过以上分析,就可以对以上的接口做进一步的修改了,大致代码如下:

    //其他代码省略
    void RegisterAdd(object entity, IUnitOfWorkRepository repository);
    

      按照这个思路的话,这个IUnitOfWorkRepository的方法数量则会跟IUnitOfWork基本相同(没有Commit),一个是注册,而另一个则是实际的操作,因此接口代码则会跟第一次改为object的相同了,代码如下:

    public interface IUnitOfWorkRepository
    {
        void ExecuteAdd(object entity);                             
        void ExecuteSave(object entity);                           
        void ExecuteRemove(object entity);
    }

      有了以上的改变之后,就可以实现IUnitOfWork了,代码结构上还是跟SQLUnitOfWork类似的,差别是原先是使用一个List<SQLEntity>来存储所有的CUD操作,但是现在必须要区分出不同类型的操作,因此需要有分别存储CUD的容器,大致代码如下:

    public class UnitOfWork : IUnitOfWork
    {
        private Dictionary<object, IUnitOfWorkRepository> m_addList = 
            new Dictionary<object, IUnitOfWorkRepository>();
        private Dictionary<object, IUnitOfWorkRepository> m_saveList =
            new Dictionary<object, IUnitOfWorkRepository>();
        private Dictionary<object, IUnitOfWorkRepository> m_removeList = 
            new Dictionary<object, IUnitOfWorkRepository>();
    
        public void RegisterAdd(object entity, IUnitOfWorkRepository repository)
        {
            if (!this.m_addList.ContainsKey(entity))
                this.m_addList.Add(entity, repository);
        }
    
        public void RegisterSave(object entity, IUnitOfWorkRepository repository)
        {
            if (!this.m_saveList.ContainsKey(entity))
                this.m_saveList.Add(entity, repository);
        }
    
        public void RegisterRemove(object entity, IUnitOfWorkRepository repository)
        {
            if (!this.m_removeList.ContainsKey(entity))
                this.m_removeList.Add(entity, repository);
        }
    
        public void Commit()
        {
            using (TransactionScope trans = new TransactionScope())
            {
                foreach (var entity in this.m_addList.Keys)
                {
                    this.m_addList[entity].ExecuteAdd(entity);
                }
    
                foreach (var entity in this.m_saveList.Keys)
                {
                    this.m_saveList[entity].ExecuteSave(entity);
                }
    
                foreach (var entity in this.m_removeList.Keys)
                {
                    this.m_removeList[entity].ExecuteRemove(entity);
                }
                trans.Complete();
            }
        }
    }
    

      到这里我们就将工作单元重构工作完成了,接下来就可以根据IUnitOfWorkRepository派生出基于ADO.NET和ORM的实现了。

    重构SchoolRepository

      首先我们先看一下重构后的代码:

    class SchoolRepository : IRepository, IUnitOfWorkRepository
    {
        private IDbConnection m_connection = null;
        private IUnitOfWork m_uow = null;
    
        public SchoolRepository(IDbConnection connection, IUnitOfWork uow)
        {
            this.m_connection = connection;
            this.m_uow = uow;
        }
    
        public void Add(object entity)
        {
            this.m_uow.RegisterAdd(entity, this);
        }
    
        public void Save(object entity)
        {
            this.m_uow.RegisterSave(entity, this);
        }
    
        public void Remove(object entity)
        {
            this.m_uow.RegisterRemove(entity, this);
        }
    
        public void ExecuteAdd(object entity)
        {
            School school = entity as School;
            using (IDbCommand cmd = this.m_connection.CreateCommand())
            {
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "insert school values(@id, @name)";
                cmd.Parameters.Add(new SqlParameter("@id", school.Id));
                cmd.Parameters.Add(new SqlParameter("@name", school.Name));
                cmd.ExecuteNonQuery();
            }
        }
    
        public void ExecuteSave(object entity)
        {
            //代码略
        }
    
        public void ExecuteRemove(object entity)
        {
            //代码略
        }
    }
    

      IRepository是数据层的基础接口,从代码中我们看到原先CUD的方法被拆分到了CUD和ExecuteXXX方法中去了,CUD方法负责调用IUnitOfWork的接口,而ExecuteXXX则实现具体的数据库操作

    基于NHibernate的IUnitOfWorkRepository实现

      先看代码吧

    class SchoolRepository : IRepository, IUnitOfWorkRepository
    {
        private IUnitOfWork m_uow = null;
    
        public SchoolRepository(IDbConnection connection, IUnitOfWork uow)
        {
            this.m_uow = uow;
        }
    
        public void Add(object entity)
        {
            this.m_uow.RegisterAdd(entity, this);
        }
    
        public void Save(object entity)
        {
            this.m_uow.RegisterSave(entity, this);
        }
    
        public void Remove(object entity)
        {
            this.m_uow.RegisterRemove(entity, this);
        }
    
        public void ExecuteAdd(object entity)
        {
            SessionFactory.CurrentSession.Add(entity);
        }
    
        public void ExecuteSave(object entity)
        {
            //代码略
        }
    
        public void ExecuteRemove(object entity)
        {
            //代码略
        }
    }
    

      从基于NHibernate的实现中,我们可以看到ExecuteXXX的方法都是去调用NHibernateSession的相关方法的。

    结尾

      到此数据层就只差查询了,下次会分享一下关于查询的模式。

      文章到这里就结束了,如果有什么问题和错误欢迎留言,谢谢!

  • 相关阅读:
    1、一条sql查询语句的执行过程
    go 内存分配
    GO Json
    gorm CRUD:读写数据
    go 基于切片的队列实现
    go的错误处理
    grpc
    sqlalchemy 判断字段是否存在
    定时函数
    用Python获取Linux资源信息的三种方法
  • 原文地址:https://www.cnblogs.com/ahl5esoft/p/4009348.html
Copyright © 2011-2022 走看看