ABP源码分析十:Unit Of Work
<p style="margin: 0; font-size: 11pt"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN">ABP以AOP的方式实现UnitOfWork功能。通过<span style="font-family: 微软雅黑" lang="en-US">UnitOfWorkRegistrar将<span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US">UnitOfWorkInterceptor<span style="font-family: 微软雅黑" lang="zh-CN">在某个类被注册到<span style="font-family: 微软雅黑" lang="en-US">IOCContainner<span style="font-family: 微软雅黑" lang="zh-CN">的时候,一并添加到该类在容器中对应的<span style="font-family: 微软雅黑" lang="en-US">ComponentModel<span style="font-family: 微软雅黑" lang="zh-CN">的<span style="font-family: 微软雅黑" lang="en-US">Interceptors<span style="font-family: 微软雅黑" lang="zh-CN">集合中。总结一句话就是,<span style="font-family: Calibri" lang="en-US">UOW<span style="font-family: 微软雅黑" lang="zh-CN">的功能是通过自定义<span style="font-family: Calibri" lang="en-US">Castle<span style="font-family: 微软雅黑" lang="zh-CN">拦截器来实现的。本文主要介绍ABP核心框架中的UnitOfWork的实现,后续会分别介绍ABP其他模块是如何具体实现IUnitOfWork的</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p><p style="margin: 0; font-size: 11pt"> </p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN">如图,AbpKernelModule调用UnitOfWorkRegister的Initialize方法将<span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US">UnitOfWorkInterceptor拦截器添加到标注了<span style="font-family: Calibri" lang="en-US">UnitOfWork<span style="font-family: 微软雅黑" lang="zh-CN">特性<span style="font-family: 微软雅黑" lang="zh-CN">方</span>法的类,以及实现<span style="font-family: 微软雅黑" lang="en-US">IRepository或<span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US">IApplicationService<span style="font-family: 微软雅黑" lang="zh-CN">的类上。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230700229-396107268.png" alt=""></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"> </p>
<p style="margin: 0; font-size: 11pt">下图是UnitOfWorkRegister的代码</p>
<p style="margin: 0; font-size: 11pt"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230710979-467482243.png" alt=""></p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"> </p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none">和通常实现的AOP一样,ABP定义了UnitOfWork特性,方便业务层为方法注入UOW功能。</p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="color: rgba(0, 0, 255, 1)">UnitOfWorkAttribute:<span style="color: rgba(0, 0, 0, 1); font-family: 微软雅黑" lang="zh-CN">用于标注某个方法位<span style="color: rgba(0, 0, 0, 1); font-family: 微软雅黑" lang="en-US">UnitOfWork<span style="color: rgba(0, 0, 0, 1); font-family: 微软雅黑" lang="zh-CN">的<span style="color: rgba(0, 0, 0, 1); font-family: 微软雅黑" lang="en-US">Attribute<span style="color: rgba(0, 0, 0, 1); font-family: 微软雅黑" lang="zh-CN">类<span style="color: rgba(0, 0, 0, 1); font-family: Calibri" lang="en-US">. <span style="color: rgba(0, 0, 0, 1); font-family: 微软雅黑" lang="zh-CN">通过这个特性,可以指定是否启用<span style="color: rgba(0, 0, 0, 1); font-family: Calibri" lang="en-US">UOW<span style="color: rgba(0, 0, 0, 1); font-family: 微软雅黑" lang="zh-CN">,事务隔离级别,<span style="font-family: 微软雅黑" lang="en-US">TransactionScopeOption<span style="font-family: 微软雅黑" lang="zh-CN">等</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="color: rgba(0, 0, 255, 1)"><span style="color: rgba(0, 0, 0, 1)"><img src="https://images2015.cnblogs.com/blog/4776/201604/4776-20160415084800020-1517830407.png" alt=""></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="color: rgba(0, 0, 255, 1)">UnitOfWorkOptions: <span style="color: rgba(0, 0, 0, 1)">封装了UnitOfWork参数的类,其实例是通过UnitOfWorkAttribute的CreateOptions来生成的。</span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"> </p>
<hr>
<p style="margin: 0; font-size: 11pt"> </p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"><strong>接下来,分析下UnitOfWork是如何封装事务的。</strong></p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none">基于接口隔离原则的考量,ABP作者将UnitOfWork的方法分到了三个不同的接口中,如下图。</p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"><span style="color: rgba(128, 0, 0, 1)">IUnitOfWorkCompleteHandle</span>:定义了UOW同步和异步的complete方法。实现UOW完成时候的逻辑。</p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"> </p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"><span style="color: rgba(128, 0, 0, 1)">IActiveUnitOfWork:</span><span style="color: rgba(0, 0, 0, 1)">一个UOW除了以上两个接口中定义的方法和属性外,其他的属性和方法都在这个接口定义的。比如Completed,Disposed,Failed事件代理,Filter的enable和disable,以及同步、异步的SaveChanges方法。</span></p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"> </p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"><span style="color: rgba(128, 0, 0, 1)">IUnitOfWork</span>:继承了上面两个接口。定义了外层的IUnitOfWork的引用和UOW的begin方法。 ABP是通过构建一个UnitOfWork的链,将不同的方法纳入到一个事务中(后文解释)。<br><br><span style="color: rgba(0, 0, 255, 1)">UnitOfWorkBase</span>:这个抽象类实现了上面三个接口中定义的方法,而真正实现事务控制的方法是由这个抽象类的子类实现的(比如,真正创建TransactionScope的操作是在<span style="color: rgba(0, 0, 255, 1)">EfUnitOfWork</span>,<span style="color: rgba(0, 0, 255, 1)">NhUnitOfWork</span>这样的之类中实现的)。UOW中除了事务控制逻辑以外的逻辑都是由UnitOfWorkBase抽象类实现的。</p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"> </p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: Calibri" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="color: rgba(0, 0, 255, 1)"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230728292-1825372742.png" alt=""></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"> </p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: Calibri" lang="en-US">ABP<span style="font-family: 微软雅黑" lang="zh-CN">中共有以下<span style="font-family: Calibri" lang="en-US">4<span style="font-family: 微软雅黑" lang="zh-CN">个具体的UOW类型,他们都继承自UnitOfWorkBase。Entity Framework, Nhibernate UnitOfWork是实现事务控制的<span style="font-family: Calibri" lang="en-US">UOW。<span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US">MongoDB <span style="font-family: 微软雅黑" lang="zh-CN">和<span style="font-family: 微软雅黑" lang="en-US"> MemoryDB UnitOfWork是没有事务控制的。 原因很简单,<span style="font-family: 微软雅黑" lang="en-US"><span style="font-family: 微软雅黑" lang="zh-CN"><span style="font-family: 微软雅黑" lang="en-US">MongoDB本身就没有完整的事务控制功能, 而ABP 框架实现的MemoryDB也是没有事务控制功能的。</span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230736792-1512699232.png" alt=""></p>
<p style="margin: 0"> </p>
<p style="margin: 0"><span style="color: rgba(128, 0, 0, 1)">IUnitOfWorkManager</span>/<span style="color: rgba(0, 0, 255, 1)">UnitOfWorkManager</span>:和其他***manager类一样是一个Facade,他对外提供UOW的功能(用于创建UnitOfWork,并开启UnitOfWork流程),对内调用各种UOW功能的各种组件。</p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230719308-2100453085.png" alt=""></p>
<p style="margin: 0"> </p>
<p style="margin: 0">UnitOfWork拦截器调用UnitOfWorkManager开启UOW流程的代码。</p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230819526-790223404.png" alt=""></p>
<p style="margin: 0; font-size: 11pt"> </p>
<p style="margin: 0; color: rgba(30, 78, 121, 1); font-size: 16pt"><span style="font-family: Calibri" lang="en-US">Unit Of Work<span style="font-family: 微软雅黑" lang="zh-CN">大致运行流程如下</span></span></p>
<ol style="font-family: 微软雅黑; font-size: 11pt; font-style: normal; font-weight: normal; margin-top: 0; margin-bottom: 0; margin-left: 0.375in; unicode-bidi: embed; direction: ltr" type="1">
<li style="margin-top: 0; margin-bottom: 0; vertical-align: middle" value="1"><span style="font-family: Calibri; font-size: 11pt; font-style: normal; font-weight: normal" lang="en-US">UOW<span style="font-family: 微软雅黑; font-size: 11pt; font-style: normal; font-weight: normal" lang="zh-CN">拦截器被注入到需要<span style="font-family: Calibri; font-size: 11pt; font-style: normal; font-weight: normal" lang="en-US">UOW<span style="font-family: 微软雅黑; font-size: 11pt; font-style: normal; font-weight: normal" lang="zh-CN">的类中。</span></span></span></span></li>
<li style="margin-top: 0; margin-bottom: 0; vertical-align: middle"><span style="font-family: Calibri; font-size: 11pt" lang="en-US">ABP<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">执行标注了UnitOfWork特性的方法时。UOW拦截器以<span style="font-family: Calibri; font-size: 11pt" lang="en-US">begin()->realAction()->complete()->dispose()<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">顺序执行,其中<span style="font-family: Calibri; font-size: 11pt" lang="en-US">realAction<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">是被调用的真实业务操作。 UOW拦截器是通过<span style="font-family: Calibri; font-size: 11pt" lang="en-US">using<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">这种方式调用IUnitOfWork<span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">的某个具体实现,这就确保<span style="font-family: Calibri; font-size: 11pt" lang="en-US">begin <span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">和<span style="font-family: Calibri; font-size: 11pt" lang="en-US"> dispose<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">也总是会被执行的。<span style="font-family: Calibri; font-size: 11pt" lang="en-US"> <span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">这里需要注意<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US">complete<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">却<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">不一定会被执行</span></span></span></span>,比如在complete方法被调用前方法的执行产生了异常。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></li>
<li style="margin-top: 0; margin-bottom: 0; vertical-align: middle"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="color: rgba(0, 0, 255, 1)">当执行一连串的操作时(A方法->B方法->C方法,假设这三个方法都标注了UnitOfWork特性),</span><span style="font-family: Calibri; font-size: 11pt" lang="en-US">ABP<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">在执行A方法前会创建整个过程中<span style="color: rgba(255, 0, 0, 1)">唯一的</span>IUnitOfWork对象<span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">,该对象<span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">会启动<span style="font-family: Calibri; font-size: 11pt" lang="en-US">.NET<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">事务。在执行到B,C方法只会创建<span style="font-family: 微软雅黑; font-size: 11pt" lang="en-US">InnerUnitOfWorkCompleteHandle。 <span style="font-family: 微软雅黑; font-size: 11pt" lang="en-US">InnerUnitOfWorkCompleteHandle与IUnitOfWork对象的差异在于</span><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">它不会创建真实的事务。但<span style="font-family: Calibri; font-size: 11pt" lang="en-US">ABP<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">会<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">调用</span>其<span style="font-family: Calibri; font-size: 11pt" lang="en-US">complete,以告知ABP<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">其对应的方法以成功完成,可以提交事务</span><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US">.</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></li>
<li style="margin-top: 0; margin-bottom: 0; vertical-align: middle"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: 微软雅黑; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN"><span style="font-family: Calibri; font-size: 11pt" lang="en-US"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">事务可以回滚的关键关键在于IUnitOfWork对象在被dispose时候会检查complete方法有没有被执行,没有的话就认为这个UOW标注的方法没有顺利完成,从而导致事务的回滚操作。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></li>
<li style="margin-top: 0; margin-bottom: 0; vertical-align: middle"><span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">整个事务的提交是通过第一个<span style="font-family: Calibri; font-size: 11pt" lang="en-US">UOW(也是唯一个)<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">的<span style="font-family: Calibri; font-size: 11pt" lang="en-US">complete<span style="font-family: 微软雅黑; font-size: 11pt" lang="zh-CN">方法执行时提交的。</span></span></span></span></span></li>
</ol>
<p style="margin: 0"> </p>
<p style="margin: 0"> </p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt"><span lang="en-US">InnerUnitOfWorkCompleteHandle关于检查complete方法有没有被执行的<span lang="zh-CN">代码</span></span></p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230745214-1732044615.png" alt=""></p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"> </p>
<p style="margin: 0; color: rgba(46, 117, 181, 1); font-size: 11pt"><span style="color: rgba(0, 0, 0, 1); font-family: 微软雅黑" lang="en-US">UnitOfWorkManager<span style="font-family: 微软雅黑" lang="zh-CN">的<span style="font-family: Calibri" lang="en-US">beign<span style="font-family: 微软雅黑" lang="zh-CN">方法。这边可以看出只有一个IUnitOfWork对象会被创建, <span style="color: rgba(255, 0, 0, 1); font-family: 微软雅黑" lang="zh-CN">而且由于这个对象是通过容器直接<span style="font-family: Calibri" lang="en-US">resolve<span style="font-family: 微软雅黑" lang="zh-CN">的,那么<span style="font-family: Calibri" lang="en-US">ABP<span style="font-family: 微软雅黑" lang="zh-CN">怎么知道该通过<span style="font-family: Calibri" lang="en-US">resolve<span style="font-family: 微软雅黑" lang="zh-CN">得到什么样的实例呢?是<span style="font-family: 微软雅黑" lang="en-US">EfUnitOfWork<span style="font-family: Calibri" lang="en-US">?<span style="font-family: 微软雅黑" lang="zh-CN">还是<span style="font-family: 微软雅黑" lang="en-US">MongoDbUnitOfWork<span style="font-family: 微软雅黑" lang="zh-CN">?还是<span style="font-family: 微软雅黑" lang="en-US">MemoryDbUnitOfWork<span style="font-family: 微软雅黑" lang="zh-CN">?还是<span style="font-family: 微软雅黑" lang="en-US">NhUnitOfWork<span style="font-family: 微软雅黑" lang="zh-CN">?答案是<span style="font-family: Calibri" lang="en-US">ABP<span style="font-family: 微软雅黑" lang="zh-CN">不知道,ABP作者假设你只会用其中一个模块,所以如果你把这四个<span style="font-family: Calibri" lang="en-US">module<span style="font-family: 微软雅黑" lang="zh-CN">都加入到你的项目中,结果是不可预知的。</span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230754448-1522466842.png" alt=""></p>
<p style="margin: 0; color: rgba(30, 78, 121, 1); font-family: Calibri; font-size: 16pt" lang="en-US"> </p>
<p style="margin: 0; color: rgba(30, 78, 121, 1); font-family: 微软雅黑; font-size: 16pt" lang="x-none"><span style="font-size: 15px">EfUnitOfWork在begin方法中创建.NET事务</span></p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230828761-216746129.png" alt=""></p>
<p style="margin: 0"> </p>
<p style="margin: 0"><span style="font-size: 15px">EfUnitOfWork</span>提交事务</p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230838104-423150805.png" alt=""></p>
<p style="margin: 0"> </p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230844979-1147771847.png" alt=""></p>
<p style="margin: 0"> </p>
<p style="margin: 0; color: rgba(30, 78, 121, 1); font-family: 微软雅黑; font-size: 16pt" lang="x-none"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230858042-2140225455.png" alt=""></p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"> </p>
<p style="margin: 0"> </p>
<p style="margin: 0; color: rgba(30, 78, 121, 1); font-family: Calibri; font-size: 16pt" lang="en-US">CallContextCurrentUnitOfWorkProvider</p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="en-US">CallContextCurrentUnitOfWorkProvider<span style="font-family: 微软雅黑" lang="zh-CN">的主要功能其实只有一个:通过<span style="font-family: Calibri" lang="en-US">current<span style="font-family: 微软雅黑" lang="zh-CN">返回当前<span style="font-family: Calibri" lang="en-US">UOW<span style="font-family: 微软雅黑" lang="zh-CN">环境下的<span style="font-family: Calibri" lang="en-US">UOW<span style="font-family: 微软雅黑" lang="zh-CN">实例。</span></span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN">一般思路是:将IUnitOfWork对象定义为实例变量或者是类变量。<span style="font-family: Calibri" lang="en-US"> <span style="font-family: 微软雅黑" lang="zh-CN">但是两者事实上都不可行。</span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN">如果定义为类变量,那就会面临线程安全的问题,解决方式无非加锁,但会导致并发能力下降,<span style="font-family: Calibri" lang="en-US">ABP<span style="font-family: 微软雅黑" lang="zh-CN">是<span style="font-family: Calibri" lang="en-US">web<span style="font-family: 微软雅黑" lang="zh-CN">框架,因为锁导致并发能力下降是不能接受的。</span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN">如果定义为实例变量,在同一线程其他地方<span style="font-family: Calibri" lang="en-US">resolve <span style="font-family: 微软雅黑" lang="en-US">CallContextCurrentUnitOfWorkProvider</span><span style="font-family: 微软雅黑" lang="zh-CN">这个实例的时候都会得到一个新的实例,新的实例下<span style="font-family: Calibri" lang="en-US">current<span style="font-family: 微软雅黑" lang="zh-CN">自然是<span style="font-family: Calibri" lang="en-US">NULL<span style="font-family: 微软雅黑" lang="en-US">.</span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: Calibri" lang="en-US"><span style="color: rgba(0, 0, 255, 1)">ABP</span><span style="font-family: 微软雅黑" lang="zh-CN"><span style="color: rgba(0, 0, 255, 1)">的做法是:线程逻辑上下文</span><span style="font-family: Calibri" lang="en-US"><span style="color: rgba(0, 0, 255, 1)">+</span><span style="font-family: 微软雅黑" lang="zh-CN"><span style="color: rgba(0, 0, 255, 1)">线程安全的</span><span style="font-family: Calibri" lang="en-US"><span style="color: rgba(0, 0, 255, 1)">Dictinoray</span><span style="font-family: 微软雅黑" lang="zh-CN"><span style="color: rgba(0, 0, 255, 1)">容器</span>。</span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN">线程逻辑上下文用于存储<span style="font-family: Calibri" lang="en-US">UOW<span style="font-family: 微软雅黑" lang="zh-CN">实例的<span style="font-family: Calibri" lang="en-US">key<span style="font-family: 微软雅黑" lang="en-US">, <span style="font-family: 微软雅黑" lang="zh-CN">而线程逻辑上下文对于本线程是全局可访问的,而同时具有天然的隔离性。这就确保了当前线程的各个地方都可以得到<span style="font-family: Calibri" lang="en-US">current<span style="font-family: 微软雅黑" lang="zh-CN">的<span style="font-family: Calibri" lang="en-US">UOW<span style="font-family: 微软雅黑" lang="zh-CN">的<span style="font-family: Calibri" lang="en-US">key</span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0; font-size: 11pt"><span style="font-family: 微软雅黑" lang="zh-CN">线程安全的<span style="font-family: Calibri" lang="en-US">Dictinoray<span style="font-family: 微软雅黑" lang="zh-CN">容器是一个类实例,用于存放<span style="font-family: Calibri" lang="en-US">UOW<span style="font-family: 微软雅黑" lang="zh-CN">的实例,通过<span style="font-family: Calibri" lang="en-US">UOW<span style="font-family: 微软雅黑" lang="zh-CN">的<span style="font-family: Calibri" lang="en-US">key<span style="font-family: 微软雅黑" lang="zh-CN">就可以取到<span style="font-family: Calibri" lang="en-US">UOW<span style="font-family: 微软雅黑" lang="zh-CN">的实例。</span></span></span></span></span></span></span></span></span></span></span></p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230802854-1843719156.png" alt=""></p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"> </p>
<p style="margin: 0"><img src="https://images2015.cnblogs.com/blog/4776/201603/4776-20160322230811448-1456711029.png" alt=""></p>
<p style="margin: 0; color: rgba(30, 78, 121, 1); font-family: 微软雅黑; font-size: 16pt" lang="x-none"> </p>
<p>返回ABP源码分析系列文章目录</p>
<p style="margin: 0"> </p>
<p style="margin: 0; font-family: 微软雅黑; font-size: 11pt" lang="x-none"> </p>
<p style="margin: 0"> </p>
<p style="margin: 0"> </p><br><br>
来源:https://www.cnblogs.com/1zhk/p/5309043.html
頁:
[1]