码迷,mamicode.com
首页 > 其他好文 > 详细

Unit Of Work的设计

时间:2016-06-17 11:08:14      阅读:297      评论:0      收藏:0      [点我收藏+]

标签:

在DDD开发过程中,一个良好的Uow设计必不可少,我心目中的Uow设计应该具备以下几点:

1、有着良好的抽象,有着恰如其分的命名;

2、能够应付不同的组件,比如你的系统中可能会存在EfUnitOfWork、RedisUnitOfWork;

3、易于使用,不用开发者显示调用。Uow在一个用户请求开始到结束能够自动包裹在业务逻辑外边;

在阅读了Abp的源码后我感觉Abp中的Uow正好符合我这几点要求,但是其实现稍有点复杂,例如在EfUnitOfWork中加入了DynamicFilters,EfUnitOfWork支持多DbContext,这些复杂性导致EfUnitOfWork类变得有点臃肿。所以我在实例代码中移除了这些设计。

一、业务抽象

一个使用Uow的典型代码片段如下:

            using (var uow = UowManager.Begin())
            {
                //....logic

                uow.Commit();
            }

从这段代码中我们基本可以分析出下面的Uow抽象。

1、IUnitOfWorkManager

技术分享

从上面的代码片段可以看出,此Manager应该具有一个Begin()方法,返回IDisposable类型。

2、IUnitOfWorkCompleteHandle

IUnitOfWorkManager的Begin()方法返回的IDisposable类型应该具有Commit()的能力,该抽象用于对IUnitOfWork的提交和释放资源。

技术分享

3、IUnitOfWork

从这个代码片段中我们并没有看到IUnitOfWork这个抽象,原因在于IUnitOfWorkManager隐藏了具体的IUnitOfWork,IUnitOfWorkManager.Begin()实现中实际上是具体的IUnitOfWork.Begin()调用。

技术分享

4、ICurrentUnitOfWorkProvider

针对用户在一次上下文中的请求,具有唯一的一个IUnitOfWork,因此可以在任意时刻通过ICurrentUnitOfWorkProvider来读取当前上下文的IUnitOfWork。

技术分享

通过接口命名描述就能理清整个Uow设计思路:

技术分享

二、EfUnitOfWork

EfUnitOfWork的Begin体现在对TransactionScope的调用、Commit体现在对dbContext.SaveChanges()的调用

        public void Begin(UnitOfWorkOptions options)
        {
            _transactionScope = new TransactionScope(
                options.TransactionScopeOption.GetValueOrDefault(_defaultUnitOfWorkOptions.TransactionScopeOption),
                new TransactionOptions()
                {
                    IsolationLevel = options.IsolationLevel.GetValueOrDefault(_defaultUnitOfWorkOptions.IsolationLevel),
                    Timeout = options.Timeout.GetValueOrDefault(_defaultUnitOfWorkOptions.Timeout)
                });
        }
        public void Complete()
        {
            try
            {
                _dbContext.SaveChanges();
                _transactionScope?.Complete();

                _completed?.Invoke();
            }
            catch
            {
                _failed?.Invoke();
                throw;
            }
           
        }

三、通过Castle实现Aop,将Uow包裹ApplicationService层

定义UnitOfWorkInterceptor,该拦截器表现为要对现有的一个方法包裹UnitOfWork实现。

        private void PerformUow(IInvocation invocation, UnitOfWorkOptions options)
        {
            using (var uow = _unitOfWorkManager.Begin(options))
            {
                invocation.Proceed();
                uow.Complete();
            }
        }

 

具体实现请参考:https://git.oschina.net/richieyangs/BookLibrary.git

Unit Of Work的设计

标签:

原文地址:http://www.cnblogs.com/richieyang/p/5593197.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!