说说IUnitOfWork~方法完整性与统一提交不冲突-阿里云开发者社区

开发者社区> 开发与运维> 正文

说说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服务。

本文转自博客园张占岭(仓储大叔)的博客,原文链接:说说IUnitOfWork~方法完整性与统一提交不冲突,如需转载请自行联系原博主。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章