说说IUnitOfWork~方法完整性与统一提交不冲突

回到目录

第一讲 认识IUnitOfWork,为什么要出现IUnitOfWork接口
第二讲 Linq to Sql与EntityFrameworks中的SubmtChanges()发生了什么事
第三讲 方法完整性与统一提交不冲突
第四讲 DbContext对象的创建应该向BLL层公开
第五讲 我的IUnitOfWork+Repository架构
 

    在一个方法中,它一般会做一件事情,这样的方法在功能上比较清晰,在职责上也很单一(这里的单一是褒义的,呵呵),而它所做的这件事,从头到尾会把它做完,不会做到一半的功能,这属于功能上的不完整,这不是我们推荐的。

项目中的代码:

完整的提交方法:

        protected virtual void SaveChanges()
        {
            if (!iUnitWork.IsNotSubmit)
                iUnitWork.Save();
        }

完整的插入方法:

       public virtual void Add(TEntity item)
        {
            _db.Entry<TEntity>(item);
            _db.Set<TEntity>().Add(item);
            this.SaveChanges();
        }

上面代码是EF实现的插入,很完善,将实现添加到实体集合,并使用SaveChanges()提交到数据库,一个完善的数据插入流程完成,但一个问题来了如果我们的

业务操作不只是插入一张表,还有更新另一张表,怎么去实现呢?

       public virtual void Modify(TEntity item)
        {
            _db.Set<TEntity>().Attach(item);
            _db.Entry(item).State = EntityState.Modified;
            this.SaveChanges();
        }

上面为完整的更新动作是上面的代码,现在有一个假设:

UserRepository类有方法Add,ProductRepository类有方法Modify,这时,这两个方法进行组织,代码可能是这样:

...code

userRepository.Add(user);

userRepository.Modify(product);

...code

      事实上,上面的代码所执行的过程为:先插入用户表,提交到SQL数据库,再更新产品表,再提交到SQL数据库,这时由于提交两次,SQL端会产生两个连接池,而如果两个方法使用了TransactionScope事务块,并且SQL服务器与WWW服务器在不同的电脑上,会触发多于的分布式事务(这是可以避免的),而我们知道,windows的MSDTC(分布式事务)服务是最不靠谱的

如何解决这种情况呢,难道方法不该完整吗?

什么事情都有解决的办法,方法的完整性在系统设计上是没有问题的,但有时,对于一个工作单元中有多个方法时,我们需要把这种完整性升级,将多个方法提升为一个整体,即多个方法的完整性问题,解决这个问题的关键在于,你的数据上下文是否为一个,你的submitChanges方法是否为一个。

IUnitWork崭新的接口规范

    /// <summary>
    /// 工作单元
    /// 提供一个保存方法,它可以对调用层公开,为了减少连库次数
    /// </summary>
    public interface IUnitOfWork
    {
        /// <summary>
        /// 将操作提交到数据库,
        /// </summary>
        void Save();
        /// <summary>
        /// 是否不提交到数据库,这只是在具体的repository类中的SaveChanges方法里用到的
        /// 默认为false,即默认为提交到数据库
        /// </summary>
        /// <returns></returns>
        bool IsNotSubmit { get; set; }
    }

    /// <summary>
    /// 工作单元
    /// 对泛型类型的支持
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public interface IUnitWork<T> : IUnitOfWork where T : class { }

看了上面的接口,不用我说,大家也知道其中的含义了,Save()为数据上下文提交,而IsNotSubmit表示是否要提交到数据库,我们都知道bool类型对象的默认

值不false,所以,默认情况下,Add,Modify这些方法的提交动作都是true,即被提交到数据库。

我们优化这时上面add与modify的方法如下:

Domain.Core.IUnitOfWork _iUnitWork = new backgroundEntities();
 _iUnitWork.IsNotSubmit=true;
userRepository(user);
productRepository(product); 
_iUnitWork.Save();

OK, 上面的代码所产生的效果就是,将两条SQL语句发到SQL端 ,使用一个SQL连接池,不产生MSDTC服务。

回到目录

posted @ 2013-03-18 22:06  张占岭  阅读(3277)  评论(2编辑  收藏  举报