﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-Artech</title><link>http://www.cnblogs.com/artech/</link><description>Develop every application as an art using the most suitable technologies!</description><language>zh-cn</language><lastBuildDate>Wed, 10 Feb 2010 02:47:15 GMT</lastBuildDate><pubDate>Wed, 10 Feb 2010 02:47:15 GMT</pubDate><ttl>60</ttl><item><title>如何通过VPC在本机搭建局域网</title><link>http://www.cnblogs.com/artech/archive/2010/02/08/1665602.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Sun, 07 Feb 2010 16:06:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/02/08/1665602.html</guid><description><![CDATA[<p>阅读: 985 评论: 14 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-02-08 00:06 <a href="http://www.cnblogs.com/artech/archive/2010/02/08/1665602.html" target="_blank">原文链接</a></p><p>前几天在家里测试一个基于WS-AT的分布式应用，但是连接公司网络的VPN出现了问题，不得不采用VPC在本机搭建一个局域网。虽然以前也做过这样的尝试，可能是很久没有弄过了，一些细节记不清了，所以也折腾了好一阵子。在这里，我特意写一篇文章来介绍基于VPC搭建局域网的整个步骤，没有什么技术含量，只当给具有相同需要的朋友多一个参考。</p>  <p>我现在的Host Machine为Windows 7 Ultimate （X64） ，Virtual Machine为Windows Server 2008 （X86），都是现成的。本篇文章不会涉及如何安全VPC的问题，仅仅涉及到如何将Host PC和VPC成为同一个局域网中两台可以互相链接的主机，下面是对3个主要步骤的：</p>  <h1><font size="4"><strong>步骤一：安装Microsoft Loopback Adapter网络适配器</strong></font></h1>  <p>打开Device Manager，右键选择主机名称，在探出的上下文菜单中选择"Add legacy hardware&#8221;。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_2.png" target="_blank"><img style="border-width: 0px; display: inline; margin-left: 0px; margin-right: 0px;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb.png" border="0" width="397" height="263" /></a> </p>  <p>出现如下一个Welcome to the Add Hardware Wizard 对象框，点击"Next&#8221;按钮。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_6.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_2.png" border="0" width="394" height="290" /></a> </p>  <p>进入如下一个对话框，选择第二个选项"Install the hardware that I manually select from a list (Advanced) "，然后点击"Next"按钮。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_8.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_3.png" border="0" width="396" height="291" /></a> </p>  <p>弹出如下一个硬件类型选择对话框，硬件类型列表中选择"Network adapter"，然后点击"Next"按钮。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_10.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_4.png" border="0" width="394" height="290" /></a> </p>  <p>硬件安装向导进入如下一个"Select Network Adapter",在硬件厂商列表中选择"Microsoft",在网络适配器列表中选择"Microsoft Loopback Adapter",然后点击"Next"按钮。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_12.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_5.png" border="0" width="397" height="292" /></a> </p>  <p>在弹出的"The wizard is ready to install your hardware"对话框中，然后点击"Next"按钮，开始安装硬件。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_14.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_6.png" border="0" width="393" height="289" /></a> </p>  <h1><font size="4"><strong>步骤二、将VPC的网络适配器设置为Microsoft Loopback Adapter</strong></font></h1>  <p>打开Virtual PC Console，选择相应的VPC，点击Setting按钮对其进行设置。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_16.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_7.png" border="0" width="389" height="275" /></a> </p>  <p>在VPC设置面板中设置项目中选择"Networking",选择我们刚才安装的"Microsoft Loopback Adapter"作为网络适配器，点击OK确认。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_20.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_9.png" border="0" width="389" height="277" /></a> </p>  <p><font size="4"><strong>步骤三、设置Host Machine和Virtual Machine的IP</strong></font></p>  <p>在Host Machine中，打开Network and Sharing Center，点击Channe Adapter Setting链接，进入Network Connections窗口。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_18.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_1.png" border="0" width="400" height="190" /></a> </p>  <p>右击选择基于Microsoft Loopback Adapter的连接（这里是Local Area Connection 2），在上下文菜单中选择Proeprties，进入连接的属性窗口。</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_22.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_8.png" border="0" width="399" height="501" /></a> </p>  <p>选择Internet Protocol Version 4（TCP/IPv4),点击 Properties按钮，进行相应的IP设置，在这里IP地址和子网掩码分别为192.168.0.6和255.255.255.0.</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_24.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_10.png" border="0" width="386" height="429" /></a> </p>  <p>然后对Virtual Machine相应的链接按照上面的步骤设置IP地址，需要设置成相同的网段，我采用的IP地址和子网掩码分别为192.168.0.8和255.255.255.0.</p>  <p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_26.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_11.png" border="0" width="384" height="426" /></a> </p>  <p>到此为止，Host Machine和Virtual Machine就成为了同一个局域网中的两个主机。你可以直接利用VPC界面操作Virtual Machine，不过我个人习惯使用Remote Desktop。此外，你可以根据具体安全需求，对防火墙进行相应设置。</p>  <p><a target="_blank" href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_28.png"><img style="border: 0px none; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/VPC_1098E/image_thumb_12.png" border="0" width="398" height="203" /></a> </p>  <div id="MySignature">作者：<a href="http://artech.cnblogs.com/" target="_blank">Artech</a>     <br />出处：<a href="http://artech.cnblogs.com/" target="_blank">http://artech.cnblogs.com</a>     <br />本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </div><img src="http://www.cnblogs.com/artech/aggbug/1665602.html?type=1" width="1" height="1" alt=""/><p>评论: 14　<a href="http://www.cnblogs.com/artech/archive/2010/02/08/1665602.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/02/08/1665602.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>谈谈分布式事务（Distributed Transaction）[共5篇]</title><link>http://www.cnblogs.com/artech/archive/2010/01/31/1660433.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Sun, 31 Jan 2010 05:22:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/01/31/1660433.html</guid><description><![CDATA[<p>阅读: 432 评论: 2 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-01-31 13:22 <a href="http://www.cnblogs.com/artech/archive/2010/01/31/1660433.html" target="_blank">原文链接</a></p><h1><font face="楷体" size="4"><strong>[第1篇] </strong></font><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html"><font face="楷体" size="4"><strong>SOA需要怎样的事务控制方式</strong></font></a></h1> <p>在一个基于SOA架构的分布式系统体系中，服务（Service）成为了基本的功能提供单元，无论与业务流程无关的基础功能，还是具体的业务逻辑，均实现在相应的服务之中。服务对外提供统一的接口，服务之间采用标准的通信方式进行交互，各个单一的服务精又有效的组合、编排成为一个有机的整体。在这样一个分布式系统中某个活动（Activity）的实现往往需要跨越单个服务的边界，如何协调多个服务之间的关系使之为活动功能的实现服务，涉及到SOA一个重要的课题：服务协作（Service Coordination）。而具体来讲，一个分布式的活动可能会执行几秒钟，比如银行转帐；也可能执行几分钟、几个小时、几天甚至更长，比如移民局处理移民的申请。事务，无疑是属于短暂运行服务协作（Short-Running Service Coordination）的范畴。</p> <h1><font face="楷体" size="4"><strong>[第2篇] </strong></font><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html"><font face="楷体" size="4"><strong>基于DTC的分布式事务管理模型之事务控制角色</strong></font></a></h1> <p>通过<a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html">上一篇</a>的介绍，我们知道了SOA真正需要的是一个能够协调服务操作直接（通过服务自身访问的资源）或者间接（通过被调用服务访问的资源）访问的所有资源的分布式事务管理系统，这是一个复杂的架构体系。WCF，作为Windows平台下基于SOA的分布式框架，对分布式事务提供全面的支持。不过，WCF并不是另起炉灶，而是充分地利用了Windows现有的事务控制基础架构。本节着重讨论Windows事务处理模型，首先来看看在这个模型中各个事务参与者各自扮演怎样的角色。</p> <h1><font face="楷体" size="4"><strong>[第3篇]</strong></font><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html"><font face="楷体" size="4"><strong>基于DTC的分布式事务管理模型之事务登记于基于2PC的事务提交</strong></font></a></h1> <p>当基于LTM或者KTM的事务提升到基于DTC的分布式事务后，DTC成为了本机所有事务型资源管理器的管理者；此外，当一个事务型操作超出了本机的范围，出现了跨机器的调用后，本机的DTC需要于被调用者所在机器的DTC进行协助。上级对下级（包括本机DTC对本机所有资源管理器，以及上下级 DTC）的管理得前提是下级在上级那里登记，即事务登记（Transaction Enlist）。所有事务参与者，包括所有资源管理器和事务管理器（即DTC）在进行了事务等级完成之后形成了一个树形的层级结构，该结构的形成是后续的事务提供成为可能，因此我们将其称之为事务提交树（Transaction Commit Tree）。 </p> <p>不同于基于单一资源管理器的本地事务，在一个分布式环境中时实现一个涉及到多个资源管理器的分布式事务，实现事务的ACID四大属性，要麻烦得多。当事务初始化服务（应用或者组件，为了更佳贴近WCF，我们都称服务）完成所有相关的操作，决定提交该事务。对于分布式事务的提交，最终的结果有两个：如果所有的操作能够顺利完成，需要持久化的数据被相应的资源管理器写入到目标资源；如果任何一个环节失败，所有持久化资源管理器将数据恢复到原来的状态。分布式事务的整个提交过程，采用两阶段提交（2PC：Two-Phase）Commit协议完成。顾名思义，&#8220;两阶段提交&#8221;意味整个整个事务提交阶段分两个阶段，我们现在就来详细介绍分别在这两个阶段中，都在做些什么。</p> <h1><font face="楷体" size="4"><strong>[第4篇]</strong></font><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html"><font face="楷体" size="4"><strong>System.Transactions事务之事务（Transaction）和可提交事务（CommittableTransaction）</strong></font></a></h1> <p>在.NET 1.x中，我们基本是通过ADO.NET实现对不同数据库访问的事务。.NET 2.0为了带来了全新的事务编程模式，由于所有事务组件或者类型均定义在<a target="_blank" href="http://msdn2.microsoft.com/a90c30fy.aspx">System.Transactions</a>程序集中的<a target="_blank" href="http://msdn2.microsoft.com/a90c30fy.aspx">System.Transactions</a>命名空间下，我们直接称基于此的事务为System.Transactions事务。System.Transactions事务编程模型使我们可以显式（通过<a target="_blank" href="http://msdn2.microsoft.com/e5c62w6d.aspx">System.Transactions.Transaction</a>）或者隐式（基于<a target="_blank" href="http://msdn2.microsoft.com/h5w5se33.aspx">System.Transactions.TransactionScope</a>）的方式进行事务编程。</p> <p>在System.Transactions事务体系下，事务本身通过类型<a target="_blank" href="http://msdn2.microsoft.com/e5c62w6d.aspx">System.Transactions.Transaction</a>类型表示。只有可提交事务才能被直接初始化，对可提交事务的提交驱动着对整个分布式事务的提交。可提交事务通过<a target="_blank" href="http://msdn2.microsoft.com/ms149647.aspx">CommittableTransaction</a>类型表示。</p> <h1><font face="楷体" size="4"><strong>[第5篇]</strong></font><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html"><font face="楷体" size="4"><strong>System.Transactions事务之依赖事务（DependentTransaction）和事务范围（TransactionScope）</strong></font></a></h1> <p><a target="_blank" href="http://msdn2.microsoft.com/e5c62w6d.aspx">Transaction</a>的定义中，信息的读者应该看到了一个叫做DepedentClone的方法。该方法对用于创建基于现有<a target="_blank" href="http://msdn2.microsoft.com/e5c62w6d.aspx">Transaction</a>对象的&#8220;依赖事务（DependentTransaction）&#8221;。不像可提交事务是一个独立的事务对象，依赖事务依附于现有的某个事务（可能是可提交事务，也可能是依赖事务）。依赖事务可以帮助我们很容易地编写一些事务型操作，当环境事务不存的时候，可以确保操作在一个独立的事务中执行；当环境事务存在的时候，则自动加入其中。</p> <p><a target="_blank" href="http://msdn2.microsoft.com/h5w5se33.aspx">TransactionScope</a>确实能够使我们的事务控制变得非常的简单。实际上，在利用System.Transactions事务进行编程的时候，我们一般不会使用到可提交事务，对于依赖事务也只有在异步调用的时候会使用到，基于<a target="_blank" href="http://msdn2.microsoft.com/h5w5se33.aspx">TransactionScope</a>的事务编程方式才是我们推荐的。 正如其名称所表现的一样，TransactionScope就是为一组事务型操作创建一个执行范围，而这个范围始于<a target="_blank" href="http://msdn2.microsoft.com/h5w5se33.aspx">TransactionScope</a>创建之时，结束于<a target="_blank" href="http://msdn2.microsoft.com/h5w5se33.aspx">TransactionScope</a>被回收（调用Dispose方法）。 </p><div id="MySignature">作者：<a href="http://artech.cnblogs.com/" target="_blank">Artech</a> <br />出处：<a href="http://artech.cnblogs.com/" target="_blank">http://artech.cnblogs.com</a> <br />本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </div><img src="http://www.cnblogs.com/artech/aggbug/1660433.html?type=1" width="1" height="1" alt=""/><p>评论: 2　<a href="http://www.cnblogs.com/artech/archive/2010/01/31/1660433.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/01/31/1660433.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>谈谈分布式事务之三: System.Transactions事务详解[下篇]</title><link>http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Sun, 31 Jan 2010 01:19:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html</guid><description><![CDATA[<p>阅读: 1269 评论: 8 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-01-31 09:19 <a href="http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html" target="_blank">原文链接</a></p><p>在<a href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html" target="_blank">前面一篇</a>给出的<a href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>的定义中，信息的读者应该看到了一个叫做DepedentClone的方法。该方法对用于创建基于现有<a href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>对象的&#8220;依赖事务（DependentTransaction）&#8221;。不像可提交事务是一个独立的事务对象，依赖事务依附于现有的某个事务（可能是可提交事务，也可能是依赖事务）。依赖事务可以帮助我们很容易地编写一些事务型操作，当环境事务不存的时候，可以确保操作在一个独立的事务中执行；当环境事务存在的时候，则自动加入其中。 </p> <h1><font size="4"><strong>一、依赖事务（Dependent Transaction）</strong></font></h1> <p>依赖事务通过<a title="DependentTransaction Class" href="http://msdn2.microsoft.com/ms149663.aspx" target="_blank">DependentTransaction</a>类型表示，<a title="DependentTransaction Class" href="http://msdn2.microsoft.com/ms149663.aspx" target="_blank">DependentTransaction</a>定义如下。和<a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>一样，<a title="DependentTransaction Class" href="http://msdn2.microsoft.com/ms149663.aspx" target="_blank">DependentTransaction</a>也是<a href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>的子类。既然<a title="DependentTransaction Class" href="http://msdn2.microsoft.com/ms149663.aspx" target="_blank">DependentTransaction</a>依赖于现有的Transaction对象而存在，相当于被依赖事务的子事务，所以无法执行对事务的提交，也自然不会定义Commit方法。但是，<a title="DependentTransaction Class" href="http://msdn2.microsoft.com/ms149663.aspx" target="_blank">DependentTransaction</a>具有一个唯一的方法成员：<strong>Complete</strong>。调用这个方法意味着向被依赖事务发送通知，表明所有与依赖事务相关的操作已经完成。</p> <div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper"> <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> [Serializable]</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">sealed</span> <span style="color: #0000ff;">class</span> DependentTransaction : Transaction</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> {  </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Complete();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> }</pre><!--CRLF--></div></div>
<p><font size="3"><strong>1、通过DependentTransaction将异步操所纳入现有事务</strong></font></p>
<p>通过<a href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>的静态属性Current表示的环境事务保存在TLS（Thread Local Storage）中，所以环境事务是基于当前线程的。这就意味着，即使环境事务存在，通过异步调用的操作也不可能自动加入到当前事务之中，因为在异步线程中感知不到环境事务的存在。在这种情况下，我们需要做的就是手工将当前事务传递到另一个线程中，作为它的环境事务。通过依赖事务我们很容易实现这一点。 </p>
<p><a title="DependentTransaction Class" href="http://msdn2.microsoft.com/ms149663.aspx" target="_blank">DependentTransaction</a>通过Transaction的DependentClone方法创建，该方法具有一个<a title="DependentCloneOption Enumeration" href="http://msdn2.microsoft.com/ms149662.aspx" target="_blank">DependentCloneOption</a>枚举类型的参数，体现了被依赖的事务再上尚未接受到依赖事务的通知（调用Complete或者Rollback方法）得情况下，提交或者完成所采取的事务控制行为。<a title="DependentCloneOption Enumeration" href="http://msdn2.microsoft.com/ms149662.aspx" target="_blank">DependentCloneOption</a>提供了两个选项，<strong>BlockCommitUntilComplete</strong>表示被依赖事务会一直等待接收到依赖事务的通知或者超过事务设定的超时时限；而<strong>RollbackIfNotComplete</strong>则会直接将被依赖的事务回滚，并抛出<a title="TransactionAbortedException Class" href="http://msdn2.microsoft.com/b997dada.aspx" target="_blank">TransactionAbortedException</a>异常。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> [Serializable]</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Transaction : IDisposable, ISerializable</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> {       </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #008000;">//其他成员</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">public</span> DependentTransaction DependentClone(DependentCloneOption cloneOption);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">enum</span> DependentCloneOption</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>     BlockCommitUntilComplete,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     RollbackIfNotComplete</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span> }</pre><!--CRLF--></div></div>
<p>下面的代码演示了如果通过依赖事务，采用异步的方式进行银行转账操作。借助于组件ThreadPool，将主线程环境事务的依赖事务传递给异步操作代理，开始异步操作的时候将此依赖事务作为当前的环境事务，那么之后的操作将自动在当前事务下进行。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Transfer(<span style="color: #0000ff;">string</span> accountFrom, <span style="color: #0000ff;">string</span> accountTo, <span style="color: #0000ff;">double</span> amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     Transaction originalTransaction = Transaction.Current;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     CommittableTransaction transaction = <span style="color: #0000ff;">new</span> CommittableTransaction();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">try</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         Transaction.Current = transaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         ThreadPool.QueueUserWorkItem(state =&gt;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>             Transaction.Current = state <span style="color: #0000ff;">as</span> DependentTransaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>             <span style="color: #0000ff;">try</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>                 Withdraw(accountFrom, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>                 Deposite(accountTo, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>                 (state <span style="color: #0000ff;">as</span> DependentTransaction).Complete();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>             }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>             <span style="color: #0000ff;">catch</span> (Exception ex)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>             {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>                 Transaction.Current.Rollback(ex);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>             }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>             <span style="color: #0000ff;">finally</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>             {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>                 (state <span style="color: #0000ff;">as</span> IDisposable).Dispose();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>                 Transaction.Current = <span style="color: #0000ff;">null</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span>             }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum26">  26:</span>         }, Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete));</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum27">  27:</span>         <span style="color: #008000;">//其他操作</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum28">  28:</span>         transaction.Commit();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum29">  29:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum30">  30:</span>     <span style="color: #0000ff;">catch</span> (TransactionAbortedException ex)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum31">  31:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum32">  32:</span>         transaction.Rollback(ex);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum33">  33:</span>         Console.WriteLine(<span style="color: #006080;">"转帐失败，错误信息：{0}"</span>, ex.InnerException.Message);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum34">  34:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum35">  35:</span>     <span style="color: #0000ff;">catch</span> (Exception ex)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum36">  36:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum37">  37:</span>         transaction.Rollback(ex);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum38">  38:</span>         <span style="color: #0000ff;">throw</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum39">  39:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum40">  40:</span>     <span style="color: #0000ff;">finally</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum41">  41:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum42">  42:</span>         Transaction.Current = originalTransaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum43">  43:</span>         transaction.Dispose();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum44">  44:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum45">  45:</span> }</pre><!--CRLF--></div></div>
<p>由于在调用DependentClone方法创建依赖事务时指定的参数为DependentCloneOption.BlockCommitUntilComplete，所以主线程在调用Commit方法提交事务的时候，由于依赖事务尚未结束（调用Complete或者Rollback方法），在这里会一直等待。如果依赖事务的Complete或者Rollback一直没有调用，那么被依赖的事务会一直等到超出事务设置的超时时限。所以，对于基于BlockCommitUntilComplete选项创建的依赖事务来说，应该及时地调用Complete或者Rollback方法。 </p>
<p><font size="3"><strong>2、通过DependentTransaction实现事务型方法</strong></font></p>
<p>这里所说的事务型方法是指方法的执行总是在事务中执行。具体来讲，有两种不同的事务应用场景：如果当前不存在环境事务，那么方法的执行将在一个独立的事务中执行；反之，如果存在环境事务，在方法执行会自动加入到环境事务之中。 </p>
<p>比如说，存储（Deposit）和提取（Withdraw）就是典型的事务型操作。对于单纯的存取款的场景，应该创建一个新的事务来控制存储和提取操作的执行，以确保单一帐户款项的数据一致性。如果在转账的场景中，应在在转账开始之前就创建一个新的事务，让提取和存储的操作自动加入到这个事务之中。 </p>
<p>我们现在就结合可提交事务和依赖事务将Deposit和Withdraw两个方法定义成事务型方法，为了相同代码的重复，在这里把事务控制部分定义在如下一个InvokeInTransaction静态方法中:</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> InvokeInTransaction(Action action)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     Transaction originalTransaction = Transaction.Current;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     CommittableTransaction committableTransaction = <span style="color: #0000ff;">null</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     DependentTransaction dependentTransaction = <span style="color: #0000ff;">null</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">null</span> == Transaction.Current)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         committableTransaction = <span style="color: #0000ff;">new</span> CommittableTransaction();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         Transaction.Current = committableTransaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>     <span style="color: #0000ff;">else</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>         dependentTransaction = Transaction.Current.DependentClone(DependentCloneOption.RollbackIfNotComplete);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>         Transaction.Current = dependentTransaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>     } </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>     <span style="color: #0000ff;">try</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>         action();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>         <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">null</span> != committableTransaction)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>         {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>             committableTransaction.Commit();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>         } </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span>         <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">null</span> != dependentTransaction)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum26">  26:</span>         {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum27">  27:</span>             dependentTransaction.Complete();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum28">  28:</span>         }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum29">  29:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum30">  30:</span>     <span style="color: #0000ff;">catch</span> (Exception ex)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum31">  31:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum32">  32:</span>         Transaction.Current.Rollback(ex);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum33">  33:</span>         <span style="color: #0000ff;">throw</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum34">  34:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum35">  35:</span>     <span style="color: #0000ff;">finally</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum36">  36:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum37">  37:</span>         Transaction transaction = Transaction.Current;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum38">  38:</span>         Transaction.Current = originalTransaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum39">  39:</span>         transaction.Dispose();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum40">  40:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum41">  41:</span> }</pre><!--CRLF--></div></div>
<p>InvokeInTransaction方法的参数是一个Action类型的代理（Delegate），表示具体的业务操作。在开始的时候记录下当前的环境事务，当整个操作结束之后应该环境事务恢复成该值。如果存在环境事务，则创建环境事务的依赖事务，反之直接创建可提交事务。并将新创建的依赖事务或者可提交事务作为当前的环境事务。将目标操作的执行（action）放在try/catch中，当目标操作顺利执行后，调用依赖事务的Complete方法或者可提交事务的Commit方法。如果抛出异常，则调用环境事务的Rollback进行回滚。在finally块中将环境事务恢复到之前的状态，并调用Dispose方法对创建的事务进行回收。 </p>
<p>借助于InvokeInTransaction这个辅助方法，我们以事务型方法的形式定义了如下的两个方法：Withdraw和Deposit，分别实现提取和存储的操作。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Withdraw(<span style="color: #0000ff;">string</span> accountId, <span style="color: #0000ff;">double</span> amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {           </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt; parameters = <span style="color: #0000ff;">new</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt;();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     parameters.Add(<span style="color: #006080;">"id"</span>, accountId);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     parameters.Add(<span style="color: #006080;">"amount"</span>, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     InvokeInTransaction(() =&gt; DbAccessUtil.ExecuteNonQuery(<span style="color: #006080;">"P_WITHDRAW"</span>, parameters));</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> }       </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Deposit(<span style="color: #0000ff;">string</span> accountId, <span style="color: #0000ff;">double</span> amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>     Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt; parameters = <span style="color: #0000ff;">new</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt;();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>     parameters.Add(<span style="color: #006080;">"id"</span>, accountId);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>     parameters.Add(<span style="color: #006080;">"amount"</span>, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>     InvokeInTransaction(() =&gt; DbAccessUtil.ExecuteNonQuery(<span style="color: #006080;">"P_DEPOSIT"</span>, parameters));</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span> }</pre><!--CRLF--></div></div>
<h1><font size="4"><strong>二、TransactionScope</strong></font></h1>
<p>在上面一节，我结合可提交事务和依赖事务，以及环境事务的机制提供了对事务型操作的实现。实际上，如果借助<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>，相应的代码将会变得非常简单。下面的代码中，通过<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>对InvokeInTransaction进行了改写，从执行效果来看这和原来的代码完全一致。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> InvokeInTransaction(Action action)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     <span style="color: #0000ff;">using</span> (TransactionScope transactionScope = <span style="color: #0000ff;">new</span> TransactionScope())</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>         action();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>         transactionScope.Complete();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span> }</pre><!--CRLF--></div></div>
<p>通过InvokeInTransaction方法前后代码的对比，我们可以明显看到<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>确实能够使我们的事务控制变得非常的简单。实际上，在利用System.Transactions事务进行编程的时候，我们一般不会使用到可提交事务，对于依赖事务也只有在异步调用的时候会使用到，基于<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>的事务编程方式才是我们推荐的。 </p>
<p>正如其名称所表现的一样，TransactionScope就是为一组事务型操作创建一个执行范围，而这个范围始于<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>创建之时，结束于<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>被回收（调用Dispose方法）。在对<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>进行深入介绍之前，照例先来看看它的定义：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">sealed</span> <span style="color: #0000ff;">class</span> TransactionScope : IDisposable</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     <span style="color: #0000ff;">public</span> TransactionScope();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> TransactionScope(Transaction transactionToUse);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">public</span> TransactionScope(TransactionScopeOption scopeOption);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">public</span> TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     <span style="color: #0000ff;">public</span> TransactionScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     <span style="color: #0000ff;">public</span> TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>     <span style="color: #0000ff;">public</span> TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout, EnterpriseServicesInteropOption interopOption);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     <span style="color: #0000ff;">public</span> TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions, EnterpriseServicesInteropOption interopOption);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>     </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Complete();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Dispose();    </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span> }</pre><!--CRLF--></div></div>
<p>我们可以看到<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>实现了IDisposable接口，除了Dispose方法之外，仅仅具有一个唯一的方法：Complete。但是<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>却有一组丰富的构造函数。我们先来看看这些构造函数相应的参数如何影响TransactionScope对事务控制的行为。 </p>
<p><strong><font size="3">1、TransactionScopeOption</font></strong><strong></strong> </p>
<p>实际上前面一节中提供的InvokeInTransaction方法基本上体现了TransactionScope的内部实现。也就是说，<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>也是通过创建可提交事务或者依赖事务，并将其作为事务范围内的环境事务，从而将范围的所有操作纳入到一个事务之中。 </p>
<p>通过在构造函数中指定<a title="TransactionScopeOption Enumeration" href="http://msdn2.microsoft.com/behwsybh.aspx" target="_blank">TransactionScopeOption</a>类型的scopeOption参数，控制<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>当环境事务存在的时候应该采取怎样的方式执行事务范围内的操作。具有来讲，具有三种不同的方式： </p>
<ul>
<li>如果已经存在环境事务，则使用该环境事务。否则，在进入范围之前创建新的事务； 
</li><li>总是为该范围创建新事务； 
</li><li>环境事务上下文在创建范围时被取消。范围中的所有操作都在无环境事务上下文的情况下完成。</li></ul>
<p><a title="TransactionScopeOption Enumeration" href="http://msdn2.microsoft.com/behwsybh.aspx" target="_blank">TransactionScopeOption</a>是一个枚举，三个枚举值Required、RequiresNew和Suppress依次对应上面的三种行为。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">enum</span> TransactionScopeOption</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     Required,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     RequiresNew,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     Suppress</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> }</pre><!--CRLF--></div></div>
<p>对于Required选项，如果当前存在环境事务<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>会创建环境事务的依赖事务，负责创建可提交事务，然后将创建的环境事务或者可提交事务作为事务范围的环境事务。如对于RequiresNew选项，TransactionScope总是会创建可提交事务并将其作为事务范围的环境事务，意味着控制事务范围内操作的事务也当前的环境事务已经没有任何关系。如果Suppress选项，<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>会将事务范围内的环境事务设为空，意味着事务范围内的操作并不受事务的控制。 </p>
<p>Required是默认选项，意味着事务范围内的事务将会作为当前环境事务的一部分。如果你不希望某个操作被纳入当前的环境事务，但是相应的操作也需要事务的控制以确保所操作数据的一致性。比如，当业务逻辑失败导致异常抛出，需要对相应的错误信息进行日志记录。对于日记的操作就可以放入基于<strong>RequiresNew</strong>选项创建<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>中。对于一些不重要的操作（操作的错误可被忽略），并且不需要通过事务来控制的操作，比如发送一些不太重要的通知，就可以采用<strong>Suppress</strong>选项。 </p>
<p><font size="3"><strong>2、TransactionOptions</strong><strong>和EnterpriseServicesInteropOption</strong></font> </p>
<p>TransactionOptions在前面已经提及，用于控制事务的超时时限和隔离级别。对于超时时限，你也可以选择TransactionScope相应能够的构造函数以TimeSpan的形式指定。而对于事务的隔离级别，需要着重强调一点：当选择TransactionScopeOption.Required选项时，TransactionScope指定的隔离级别必须与环境事务（如果有）相匹配。 </p>
<p>比如下面的例子中，我定义两个嵌套的<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>，外部的<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>采用默认的隔离级别，内部在采用ReadCommitted隔离级别，当执行这段代码的时候，会抛出如<strong>图1</strong>所示的<a title="ArgumentException Class" href="http://msdn2.microsoft.com/3w1b3114.aspx" target="_blank">ArgumentException</a>异常。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> (TransactionScope outerScope = <span style="color: #0000ff;">new</span> TransactionScope())</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     TransactionOptions transactionOptions = <span style="color: #0000ff;">new</span> TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted };</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">using</span> (TransactionScope innerScope = <span style="color: #0000ff;">new</span> TransactionScope(TransactionScopeOption.Required, transactionOptions))</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>         <span style="color: #008000;">//事务型操作</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         innerScope.Complete();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>     <span style="color: #008000;">//事务型操作</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     outerScope.Complete();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span> }</pre><!--CRLF--></div></div>
<p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/System.Transactions_12BC4/image_2.png" target="_blank"><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/System.Transactions_12BC4/image_thumb.png" width="522" border="0" height="190" /></a></p>
<p align="center"><strong>图1 隔离级别不一致导致的异常</strong></p>
<p>实际上在System.Transactions事务机制被引入之前，像Enterprise Service主要依赖于基于COM+的分布式事务。TransactionScope通过EnterpriseServicesInteropOption控制System.Transactions事务如何与COM+的分布式事务进行互操作。具有来讲具有如下三种互操作选项，分别和EnterpriseServicesInteropOption三个枚举值相对应： </p>
<ul>
<li>None：Transaction 和 Current 之间不同步； 
</li><li>Automatic：搜索现有的 COM+ 上下文并与之同步（如该上下文存在）； 
</li><li>Full：System.EnterpriseServices 上下文（可通过调用 ContextUtil 类的静态方法 Transaction 来检索）和 System.Transactions 环境事务（可通过调用 Transaction 类的静态方法 Current 来检索）始终保持同步。这将引入性能损失，因为可能需要创建新的 System.EnterpriseServices 上下文。</li></ul>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">enum</span> EnterpriseServicesInteropOption</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     None,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     Automatic,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     Full</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> }</pre><!--CRLF--></div></div>
<p><strong><font size="3">3、事务提交和回滚</font></strong> </p>
<p>对于事务范围中的事务，无论是事务的提交（对于可提交事务）、完成（依赖事务）和回滚都是在Dispose方法中执行的。TransactionScope中定一个个私有的布尔类型字段（complete）表示事务是否正常结束。该成员的默认值为False，当调用TransactionScope的Complete方法的时候会将此字段设置成True。当Dispose执行的时候，如果该字段的值为False，会调用事务的Rollback方法对该事务实施回滚；否则会调用Commit方法（对于可提交事务）对事务进行提交或者调用Complete方法（依赖事务）通知被依赖的事务本地事务已经正常完成。 </p>
<p>除了执行事务的提交、完成或者回滚之外，TransactionScope的Dispose方法还负责将环境事务回复到事务范围开始之前的状态。在调用Complete和Dispose之前，环境事务处于不可用的状态，如果此时试图获取环境事务，会抛出异常。比如在下面的代码中，在事务范围内部调用Complete方法后，通过Transaction的Current静态属性获取当前环境事务，会抛出<strong>图2</strong>所示的InvalidOpertionException异常。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> (TransactionScope transactionScope = <span style="color: #0000ff;">new</span> TransactionScope())</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     <span style="color: #008000;">//其他事务操作</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     transactionScope.Complete();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     Transaction ambientTransaction = Transaction.Current;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> }  </pre><!--CRLF--></div></div>
<p align="center"><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/System.Transactions_12BC4/image_4.png" target="_blank"><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/System.Transactions_12BC4/image_thumb_1.png" width="516" border="0" height="175" /></a>&nbsp;<strong>图2 在TransactionScope完成之后获取环境事务导致的异常</strong></p>
<p><strong>分布式事务系列:<br /></strong><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html">谈谈分布式事务之一：SOA需要怎样的事务控制方式</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[下篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html">谈谈分布式事务之三: System.Transactions事务详解[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html">谈谈分布式事务之三: System.Transactions事务详解[下篇]</a></p>
<div id="MySignature">作者：<a href="http://artech.cnblogs.com/" target="_blank">Artech</a> <br />出处：<a href="http://artech.cnblogs.com/" target="_blank">http://artech.cnblogs.com</a> <br />本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </div><img src="http://www.cnblogs.com/artech/aggbug/1660356.html?type=1" width="1" height="1" alt=""/><p>评论: 8　<a href="http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>谈谈分布式事务之三: System.Transactions事务详解[上篇]</title><link>http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Sat, 30 Jan 2010 08:49:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html</guid><description><![CDATA[<p>阅读: 1192 评论: 4 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-01-30 16:49 <a href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html" target="_blank">原文链接</a></p><p>在.NET 1.x中，我们基本是通过ADO.NET实现对不同数据库访问的事务。.NET 2.0为了带来了全新的事务编程模式，由于所有事务组件或者类型均定义在<a title="System.Transactions Namespace" href="http://msdn2.microsoft.com/a90c30fy.aspx" target="_blank">System.Transactions</a>程序集中的<a title="System.Transactions Namespace" href="http://msdn2.microsoft.com/a90c30fy.aspx" target="_blank">System.Transactions</a>命名空间下，我们直接称基于此的事务为System.Transactions事务。System.Transactions事务编程模型使我们可以显式（通过<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">System.Transactions.Transaction</a>）或者隐式（基于<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">System.Transactions.TransactionScope</a>）的方式进行事务编程。我们先来看看，这种全新的事务如何表示。 </p> <h1><font size="4"><strong>一、System.Transactions.Transaction</strong></font></h1> <p>在System.Transactions事务体系下，事务本身通过类型<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">System.Transactions.Transaction</a>类型表示，下面是<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>的定义：</p> <div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper"> <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> [Serializable]</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Transaction : IDisposable, ISerializable</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> {   </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">event</span> TransactionCompletedEventHandler TransactionCompleted;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">public</span> Transaction Clone();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     <span style="color: #0000ff;">public</span> DependentTransaction DependentClone(DependentCloneOption cloneOption);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>     <span style="color: #0000ff;">public</span> Enlistment EnlistDurable(Guid resourceManagerIdentifier, IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     <span style="color: #0000ff;">public</span> Enlistment EnlistDurable(Guid resourceManagerIdentifier, ISinglePhaseNotification singlePhaseNotification, EnlistmentOptions enlistmentOptions);    </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">bool</span> EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification);  </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>     <span style="color: #0000ff;">public</span> Enlistment EnlistVolatile(IEnlistmentNotification enlistmentNotification, EnlistmentOptions enlistmentOptions);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>     <span style="color: #0000ff;">public</span> Enlistment EnlistVolatile(ISinglePhaseNotification singlePhaseNotification, EnlistmentOptions enlistmentOptions);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Rollback();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Rollback(Exception e);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>     <span style="color: #0000ff;">void</span> ISerializable.GetObjectData(SerializationInfo serializationInfo, StreamingContext context);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> Transaction Current { get; set; }   </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>  </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>     <span style="color: #0000ff;">public</span> IsolationLevel IsolationLevel { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>     <span style="color: #0000ff;">public</span> TransactionInformation TransactionInformation { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span> }</pre><!--CRLF--></div></div>
<p><font size="3"><strong>1、Transaction是可序列化的</strong></font></p>
<p>从上面的定义我们可以看到，<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>类型（在没有特殊说明的情况下，以下的Transaction类型指的就是<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">System.Transactions.Transaction</a>）上面应用的<a title="SerializableAttribute Class" href="http://msdn2.microsoft.com/bcfsa90a.aspx" target="_blank">SerializableAttribute</a>特性，并且实现了<a title="ISerializable Interface" href="http://msdn2.microsoft.com/wf4375ks.aspx" target="_blank">ISerializable</a>接口，意味着一个<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>对象是可以被序列化的。<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>的这一特性在WCF整个分布式事务的实现意义重大，原因很简单：<strong>要让事务能够控制整个服务操作，必须实现事务的传播，而传播的前提就是事务可被序列化</strong>。 </p>
<p><font size="3"><strong>2、如何登记事务参与者</strong></font></p>
<p>在<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>中，定义了五个EnlistXxx方法用于将涉及到的资源管理器登记到当前事务中。其中EnlistDurable和EnlistVolatile分别实现了对持久化资源管理器和易失资源管管理器的事务登记，而EnlistPromotableSinglePhase则针对的是可被提升的资源管理器（比如基于SQL Server 2005和SQL Server 2008）。 </p>
<p>事务登记的目的是建立事务提交树，使得处于根节点的事务管理器能够在事务提交的时候能够沿着这棵树将相应的通知发送给所有的事务参与者。这种至上而下的通知机制依赖于具体采用事务提交协议，或者说某个资源要求参与到当前事务之中，必须满足基于协议需要的接收和处理相应通知的能力。System.Transactions将不同事务提交协议对参与者的要求定义在相应的接口中。其中<a title="IEnlistmentNotification Interface" href="http://msdn2.microsoft.com/b3b0471d.aspx" target="_blank">IEnlistmentNotification</a>和<a title="ISinglePhaseNotification Interface" href="http://msdn2.microsoft.com/xa28ab1y.aspx" target="_blank">ISinglePhaseNotification</a>分别是基于2PC和SPC（关于2PC和SPC，在<a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html" target="_blank">上篇</a>中有详细的介绍）。 </p>
<p>如果我们需要为相应的资源开发能够参与到System.Transactions事务的资源管理器，需要事先实现<a title="IEnlistmentNotification Interface" href="http://msdn2.microsoft.com/b3b0471d.aspx" target="_blank">IEnlistmentNotification</a>接口，对基本的2PC协议提供支持。当满足SPC要求的时候，如果希望采用SPC优化协议，则需要实现<a title="ISinglePhaseNotification Interface" href="http://msdn2.microsoft.com/xa28ab1y.aspx" target="_blank">ISinglePhaseNotification</a>接口。如果希望像SQL Server 2005或者SQL Server 2008支持事务提升机制，则需要实现<a title="IPromotableSinglePhaseNotification Interface" href="http://msdn2.microsoft.com/8zhhcx4f.aspx" target="_blank">IPromotableSinglePhaseNotification</a>接口。 </p>
<p><font size="3"><strong>3、环境事务（Ambient Transaction）</strong></font></p>
<p>Transaction定义了一个类型为Transaction的Current静态属性（可读可写），表示当前的事务。作为当前事务的Transaction存储于当前线程的TLS（Thread Local Storage）中（实际上是定义在一个应用了<a title="ThreadStaticAttribute Class" href="http://msdn2.microsoft.com/h3811ycd.aspx" target="_blank">ThreadStaticAttribute</a>特性的静态字段上），所以仅对当前线程有效。如果进行异步调用，当前事务并不能自动事先跨线程传播，将异步操作纳入到当前事务，需要使用到另外一个事务：依赖事务。 </p>
<p>这种基于当前线程的当前事务又称<strong>环境事务（Ambient Transaction）</strong>，很多资源管理器都具有对环境事务的感知能力。也就是说，如果我们通过Current属性设置了环境事务，当对某个具有环境事务感知能力的资源管理器进行访问的时候，相应的资源管理器会自动登记到当前事务中来。我们将具有这种感知能力的资源管理器称为System.Transactions资源管理器。 </p>
<p><font size="3"><strong>4、事务标识</strong></font></p>
<p>Transaction具有一个只读的TransactionInformation属性，表示事务一些基本的信息。属性的类型为<a title="TransactionInformation Class" href="http://msdn2.microsoft.com/ms149812.aspx" target="_blank">TransactionInformation</a>，定义如下：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> TransactionInformation</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {  </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     <span style="color: #0000ff;">public</span> DateTime CreationTime { get; }    </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> TransactionStatus Status { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> LocalIdentifier { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     <span style="color: #0000ff;">public</span> Guid DistributedIdentifier { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span> }</pre><!--CRLF--></div></div>
<p><a title="TransactionInformation Class" href="http://msdn2.microsoft.com/ms149812.aspx" target="_blank">TransactionInformation</a>的CreationTime和Status表示创建事务的时间和事务的当前状态。事务具有活动（Active）、提交（Committed）、中止（Aborted）和未决（In-Doubt）四种状态，通过<a title="TransactionStatus Enumeration" href="http://msdn2.microsoft.com/e3ftf9sa.aspx" target="_blank">TransactionStatus</a>枚举表示。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">enum</span> TransactionStatus</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     Active,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     Committed,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     Aborted,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     InDoubt</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> }</pre><!--CRLF--></div></div>
<p>事务具有两个标识符，一个是本地标识，另一个是分布式标识，分别通过TransactionInformation的只读属性LocalIdentifier和DistributedIdentifier表示。本地标识由两部分组成：标识为本地应用程序域分配的轻量级事务管理器（LTM）的GUID和一个递增的整数（表示当前LMT管理的事务序号）。在下面的代码中，我们分别打印出三个新创建的可提交事务（<a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>，为Transaction的子类，我们后面会详细介绍）的本地标识。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">using</span> System.Transactions;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> <span style="color: #0000ff;">class</span> Proggram</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main()</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         Console.WriteLine(<span style="color: #0000ff;">new</span> CommittableTransaction().TransactionInformation.LocalIdentifier);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         Console.WriteLine(<span style="color: #0000ff;">new</span> CommittableTransaction().TransactionInformation.LocalIdentifier);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         Console.WriteLine(<span style="color: #0000ff;">new</span> CommittableTransaction().TransactionInformation.LocalIdentifier);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span> }</pre><!--CRLF--></div></div>
<p>输出结果：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">AC48F192-4410-45fe-AFDC-8A890A3F5634：1</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">AC48F192-4410-45fe-AFDC-8A890A3F5634：2</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">AC48F192-4410-45fe-AFDC-8A890A3F5634：3</pre><!--CRLF--></div></div>
<p>一旦本地事务提升到基于DTC的分布式事务，系统会为之生成一个GUID作为其唯一标识。当事务跨边界执行的时候，分布式事务标识会随着事务一并被传播，所以在不同的执行上下文中，你会得到相同的GUID。分布式事务标识通过TransactionInformation的只读属性DistributedIdentifier表示，我经常在审核（Audit）中使用该标识。 </p>
<p>对于上面Transaction的介绍，细心的读者可能会发现两个问题：Transaction并没有提供公有的构造函数，意味着我们不能直接通过new操作符创建Transaction对象；Transaction只有两个重载的Rollback方法，并没有Commit方法，意味着我们直接通过Transaction进行事务提交。 </p>
<p>在一个分布式事务中，事务初始化和提交只能有相同的参与者担当。也就是说只有被最初开始的事务才能被提交，我们将这种能被初始化和提交的事务称作可提交事务（Committable Transaction）。随着分布式事务参与者逐个登记到事务之中，它们本地的事务实际上依赖着这个最初开始的事务，所以我们称这种事务为依赖事务（Dependent Transaction）。 </p>
<h1><font size="4"><strong>二、 可提交事务(CommittableTransaction)</strong></font></h1>
<p>只有可提交事务才能被直接初始化，对可提交事务的提交驱动着对整个分布式事务的提交。可提交事务通过<a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>类型表示。照例先来看看<a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>的定义：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> [Serializable]</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">sealed</span> <span style="color: #0000ff;">class</span> CommittableTransaction : Transaction, IAsyncResult</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> {   </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> CommittableTransaction();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">public</span> CommittableTransaction(TimeSpan timeout);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">public</span> CommittableTransaction(TransactionOptions options);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Commit();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>     <span style="color: #0000ff;">public</span> IAsyncResult BeginCommit(AsyncCallback asyncCallback, <span style="color: #0000ff;">object</span> asyncState);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> EndCommit(IAsyncResult asyncResult);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>    </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>     <span style="color: #0000ff;">object</span> IAsyncResult.AsyncState { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>     WaitHandle IAsyncResult.AsyncWaitHandle { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>     <span style="color: #0000ff;">bool</span> IAsyncResult.CompletedSynchronously { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>     <span style="color: #0000ff;">bool</span> IAsyncResult.IsCompleted { get; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span> }</pre><!--CRLF--></div></div>
<p><font size="3"><strong>1、可提交事务的超时时限和隔离级别</strong></font></p>
<p><a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>直接继承自<a title="Transaction Class" href="http://msdn2.microsoft.com/e5c62w6d.aspx" target="_blank">Transaction</a>，提供了三个公有的构造函数。通过TimeSpan类型的timeout参数指定事务的超时实现，自被初始化那一刻开始算起，一旦超过了该时限，事务会被中止。通过<a title="TransactionOptions Structure" href="http://msdn2.microsoft.com/ea549tf1.aspx" target="_blank">TransactionOptions</a>类型的options可以同时指定事务的超时时限和隔离级别。<a title="TransactionOptions Structure" href="http://msdn2.microsoft.com/ea549tf1.aspx" target="_blank">TransactionOptions</a>是一个定义在System.Transactions命名空间下的结构（Struct），定义如下，两个属性Timeout和IsolationLevel分别代表事务的超时时限和隔离级别。 </p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> [StructLayout(LayoutKind.Sequential)]</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">struct</span> TransactionOptions</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #008000;">//其他成员</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">public</span> TimeSpan Timeout { get; set; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">public</span> IsolationLevel IsolationLevel { get; set; }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> }</pre><!--CRLF--></div></div>
<p>如果调用默认无参的构造函数来创建<a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>对象，意味着采用一个默认的超时时限。这个默认的时间是1分钟，不过可以它可以通过配置的方式进行指定。事务超时时限相关的参数定义在&lt;system.transactions&gt;配置节中，下面的XML体现的是默认的配置。从该段配置我们可以看到，我们不但可以通过&lt;defaultSettings&gt;设置事务默认的超时时限，还可以通过&lt;machineSettings&gt;设置最高可被允许的事务超时时限，默认为10分钟。在对这两项进行配置的时候，前者的时间必须小于后者，否则将用后者作为事务默认的超时时限。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">&lt;?</span><span style="color: #800000;">xml</span> <span style="color: #ff0000;">version</span><span style="color: #0000ff;">="1.0"</span> <span style="color: #ff0000;">encoding</span><span style="color: #0000ff;">="utf-8"</span> ?<span style="color: #0000ff;">&gt;</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">configuration</span><span style="color: #0000ff;">&gt;</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>   <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">system.transactions</span><span style="color: #0000ff;">&gt;</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">defaultSettings</span> <span style="color: #ff0000;">timeout</span><span style="color: #0000ff;">="00:01:00"</span><span style="color: #0000ff;">/&gt;</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">machineSettings</span> <span style="color: #ff0000;">maxTimeout</span><span style="color: #0000ff;">="00:10:00"</span><span style="color: #0000ff;">/&gt;</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>   <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">system.transactions</span><span style="color: #0000ff;">&gt;</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> <span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">configuration</span><span style="color: #0000ff;">&gt;</span></pre><!--CRLF--></div></div>
<p>作为事务ACID四大属性之一的隔离性（Isolation），确保事务操作的中间状态的可见性仅限于事务内部。隔离机制通过对访问的数据进行加锁，防止数据被事务的外部程序操作，从而确保了数据的一致性。但是隔离机制在另一方面又约束了对数据的并发操作，降低数据操作的整体性能。为了权衡着两个互相矛盾的两个方面，我们可以根据具体的情况选择相应的隔离级别。 </p>
<p>在System.Transactions事务体系中，为事务提供了7种不同的隔离级别。这7中隔离级别分别通过<a title="IsolationLevel Enumeration" href="http://msdn2.microsoft.com/248t96aw.aspx" target="_blank">System.Transactions.IsolationLevel</a>的7个枚举项表示。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">enum</span> IsolationLevel</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     Serializable,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     RepeatableRead,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     ReadCommitted,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     ReadUncommitted,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     Snapshot,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     Chaos,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>     Unspecified</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span> }</pre><!--CRLF--></div></div>
<p>7个隔离级别之中，Serializable具有最高隔离级别，代表的是一种完全基于序列化（同步）的数据存取方式，这也是System.Transactions事务默认采用的隔离级别。按照隔离级别至高向低，7个不同的隔离级别代表的含义如下： </p>
<ul>
<li><strong>Serializable</strong>：可以在事务期间读取可变数据，但是不可以修改，也不可以添加任何新数据； 
</li><li><strong>RepeatableRead</strong>：可以在事务期间读取可变数据，但是不可以修改。可以在事务期间添加新数据； 
</li><li><strong>ReadCommitted</strong>：不可以在事务期间读取可变数据，但是可以修改它； 
</li><li><strong>ReadUncommitted</strong>：可以在事务期间读取和修改可变数据； 
</li><li><strong>Snapshot</strong>：可以读取可变数据。在事务修改数据之前，它验证在它最初读取数据之后另一个事务是否更改过这些数据。如果数据已被更新，则会引发错误。这样使事务可获取先前提交的数据值； 
</li><li><strong>Chaos</strong>：无法覆盖隔离级别更高的事务中的挂起的更改； 
</li><li><strong>Unspecified</strong>：正在使用与指定隔离级别不同的隔离级别，但是无法确定该级别。如果设置了此值，则会引发异常。</li></ul>
<p><font size="3"><strong>2、事务的提交</strong></font></p>
<p><a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>提供了同步（通过Commit方法）和异步（通过BeginCommit|EndCommit方法组合）对事务的提交。此外<a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>还是实现了<a title="IAsyncResult Interface" href="http://msdn2.microsoft.com/ft8a6455.aspx" target="_blank">IAsyncResult</a>这么一个接口，如果采用异步的方式调用BeginCommit方法提交事务，方法返回的<a title="IAsyncResult Interface" href="http://msdn2.microsoft.com/ft8a6455.aspx" target="_blank">IAsyncResult</a>对象的各属性值会反映在<a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>同名属性上面。 </p>
<p>前面我们提到了环境事务已经System.Transactions资源管理器对环境事务的自动感知能力。当创建了<a title="CommittableTransaction Class" href="http://msdn2.microsoft.com/ms149647.aspx" target="_blank">CommittableTransaction</a>对象的时候，被创建的事务并不会自动作为环境事务，你需要手工将其指定到Transaction的静态Current属性中。接下来，我们将通过一个简单的例子演示如果通过CommittableTransaction实现一个分布式事务。 </p>
<p><font size="3"><strong>3、实例演示：通过CommittableTransaction实现分布式事务</strong></font></p>
<p>在这个实例演示中，我们沿用介绍事务显式控制时使用到的银行转帐的场景，并且直接使用<a href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html" target="_blank">第一篇</a>中创建的帐户表（T_ACCOUNT）。一个完整的转帐操作本质上有两个子操作完成，提取和存储，即从一个帐户中提取相应的金额存入另一个帐户。为了完成这两个操作，我写了如下两个存储过程：P_WITHDRAW和P_DEPOSIT。 </p>
<p>P_WITHDRAW：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">Procedure</span> P_WITHDRAW</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span>     (</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>         @id        <span style="color: #0000ff;">VARCHAR</span>(50),</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>         @amount <span style="color: #0000ff;">FLOAT</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     )</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> <span style="color: #0000ff;">AS</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> <span style="color: #0000ff;">IF</span> <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">EXISTS</span>(<span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> [dbo].[T_ACCOUNT] <span style="color: #0000ff;">WHERE</span> ID = @id)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         <span style="color: #0000ff;">RAISERROR</span> (<span style="color: #006080;">'帐户ID不存在'</span>,16,1)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>         <span style="color: #0000ff;">RETURN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>     <span style="color: #0000ff;">END</span>    </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span> <span style="color: #0000ff;">IF</span> <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">EXISTS</span>(<span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> [dbo].[T_ACCOUNT] <span style="color: #0000ff;">WHERE</span> ID = @id <span style="color: #0000ff;">AND</span> BALANCE &gt; @amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>     <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>         <span style="color: #0000ff;">RAISERROR</span> (<span style="color: #006080;">'余额不足'</span>,16,1)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>         <span style="color: #0000ff;">RETURN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>     <span style="color: #0000ff;">END</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>     </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span> <span style="color: #0000ff;">UPDATE</span>     [dbo].[T_ACCOUNT] <span style="color: #0000ff;">SET</span> Balance = Balance - @amount <span style="color: #0000ff;">WHERE</span> Id = @id</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span> <span style="color: #0000ff;">GO</span></pre><!--CRLF--></div></div>
<p>P_DEPOSIT：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">Procedure</span> P_DEPOSIT</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span>     (</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>         @id        <span style="color: #0000ff;">VARCHAR</span>(50),</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>         @amount <span style="color: #0000ff;">FLOAT</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     )</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> <span style="color: #0000ff;">AS</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> <span style="color: #0000ff;">IF</span> <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">EXISTS</span>(<span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> [dbo].[T_ACCOUNT] <span style="color: #0000ff;">WHERE</span> Id = @id)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         <span style="color: #0000ff;">RAISERROR</span> (<span style="color: #006080;">'帐户ID不存在'</span>,16,1)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     <span style="color: #0000ff;">END</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span> <span style="color: #0000ff;">UPDATE</span>     [dbo].[T_ACCOUNT] <span style="color: #0000ff;">SET</span> Balance = Balance + @amount <span style="color: #0000ff;">WHERE</span> Id = @id</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span> <span style="color: #0000ff;">GO</span></pre><!--CRLF--></div></div>
<p>为了确定是否成功转帐，我们需要提取相应帐户的当前余额，我们相应操作实现在下面一个存储过程中。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">Procedure</span> P_GET_BALANCE_BY_ID</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span>     (</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>         @id <span style="color: #0000ff;">VARCHAR</span>(50)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     )</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> <span style="color: #0000ff;">AS</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> <span style="color: #0000ff;">IF</span> <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">EXISTS</span>(<span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> [dbo].[T_ACCOUNT] <span style="color: #0000ff;">WHERE</span> Id = @id)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         <span style="color: #0000ff;">RAISERROR</span> (<span style="color: #006080;">'帐户ID不存在'</span>,16,1)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>     <span style="color: #0000ff;">END</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span> <span style="color: #0000ff;">SELECT</span> BALANCE <span style="color: #0000ff;">FROM</span> [dbo].[T_ACCOUNT] <span style="color: #0000ff;">WHERE</span> Id = @id</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span> <span style="color: #0000ff;">GO</span></pre><!--CRLF--></div></div>
<p>为了执行存储过程的方便，我写了一个简单的工具类DbAccessUtil。ExecuteNonQuery和ExecuteScalar的作用于DbCommand同名方法相同。使用DbAccessUtil的这两个方法，只需要以字符串和字典的方式传入存储过程名称和参数即可。由于篇幅所限，关于具有实现不再多做介绍了，又兴趣的读者，可以参考《<a href="http://www.china-pub.com/46907&amp;ref=ps" target="_blank">WCF技术剖析（卷1）</a>》的最后一章，里面的DbHelper提供了相似的实现。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span> DbAccessUtil</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">int</span> ExecuteNonQuery(<span style="color: #0000ff;">string</span> procedureName, IDictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt; parameters);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> T ExecuteScalar&lt;T&gt;(<span style="color: #0000ff;">string</span> procedureName, IDictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt; parameters);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> }</pre><!--CRLF--></div></div>
<p>借助于DbAccessUtil提供的辅助方法，我们定义两个方法Withdraw和Deposit分别实现提取和存储的操作,已近获取某个帐户当前余额。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Withdraw(<span style="color: #0000ff;">string</span> accountId, <span style="color: #0000ff;">double</span> amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt; parameters = <span style="color: #0000ff;">new</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt;();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     parameters.Add(<span style="color: #006080;">"id"</span>, accountId);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     parameters.Add(<span style="color: #006080;">"amount"</span>, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     DbAccessUtil.ExecuteNonQuery(<span style="color: #006080;">"P_DEPOSIT"</span>, parameters);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> } </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Deposite(<span style="color: #0000ff;">string</span> accountId, <span style="color: #0000ff;">double</span> amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>     Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt; parameters = <span style="color: #0000ff;">new</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt;();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>     parameters.Add(<span style="color: #006080;">"id"</span>, accountId);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>     parameters.Add(<span style="color: #006080;">"amount"</span>, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>     DbAccessUtil.ExecuteNonQuery(<span style="color: #006080;">"P_DEPOSIT"</span>, parameters);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span> }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">double</span> GetBalance(<span style="color: #0000ff;">string</span> accountId)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>     Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt; parameters = <span style="color: #0000ff;">new</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, <span style="color: #0000ff;">object</span>&gt;();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>     parameters.Add(<span style="color: #006080;">"id"</span>, accountId);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>     <span style="color: #0000ff;">return</span> DbAccessUtil.ExecuteScalar&lt;<span style="color: #0000ff;">double</span>&gt;(<span style="color: #006080;">"P_GET_BALANCE_BY_ID"</span>, parameters);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span> }</pre><!--CRLF--></div></div>
<p>现在假设帐户表中有一个帐号，它们的ID分别为Foo，余额为5000。下面是没有采用事务机制的转帐实现（注意：<strong>需要转入的帐户不存在</strong>）。</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">using</span> System.Collections.Generic;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> <span style="color: #0000ff;">namespace</span> Artech.TransactionDemo</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">class</span> Program</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span>[] args)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>             <span style="color: #0000ff;">string</span> accountFoo = <span style="color: #006080;">"Foo"</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>             <span style="color: #0000ff;">string</span> nonExistentAccount = Guid.NewGuid().ToString();            </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>             <span style="color: #008000;">//输出转帐之前的余额</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             Console.WriteLine(<span style="color: #006080;">"帐户\"{0}\"的当前余额为：￥{1}"</span>, accountFoo, GetBalance(accountFoo));</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>             <span style="color: #008000;">//开始转帐    </span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>             <span style="color: #0000ff;">try</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>             {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>                 Transfer(accountFoo, nonExistentAccount, 1000);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>             }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>             <span style="color: #0000ff;">catch</span> (Exception ex)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>             {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>                 Console.WriteLine(<span style="color: #006080;">"转帐失败，错误信息：{0}"</span>, ex.Message);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>             }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>             <span style="color: #008000;">//输出转帐后的余额</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>             Console.WriteLine(<span style="color: #006080;">"帐户\"{0}\"的当前余额为：￥{1}"</span>, accountFoo, GetBalance(accountFoo));</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>         }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum26">  26:</span>         <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Transfer(<span style="color: #0000ff;">string</span> accountFrom, <span style="color: #0000ff;">string</span> accountTo, <span style="color: #0000ff;">double</span> amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum27">  27:</span>         {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum28">  28:</span>             Withdraw(accountFrom, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum29">  29:</span>             Deposite(accountTo, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum30">  30:</span>         }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum31">  31:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum32">  32:</span> }</pre><!--CRLF--></div></div>
<p>输出结果：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">帐户<span style="color: #006080;">"Foo"</span>的当前余额为：￥5000</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">转帐失败，错误信息：帐户ID不存在</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">帐户<span style="color: #006080;">"Foo"</span>的当前余额为：￥4000</pre><!--CRLF--></div></div>
<p>由于没有采用事务，在转入帐户根本不存在情况下，款项依然被转出帐户提取出来。现在我们通过CommittableTransaction将整个转帐操作纳入同一个事务中，只需要将Transfer方法进行如下的改写：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Transfer(<span style="color: #0000ff;">string</span> accountFrom, <span style="color: #0000ff;">string</span> accountTo, <span style="color: #0000ff;">double</span> amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     Transaction originalTransaction = Transaction.Current;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     CommittableTransaction transaction = <span style="color: #0000ff;">new</span> CommittableTransaction();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">try</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         Transaction.Current = transaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         Withdraw(accountFrom, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         Deposite(accountTo, amount);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>         transaction.Commit();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>     <span style="color: #0000ff;">catch</span> (Exception ex)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>         transaction.Rollback(ex);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>         <span style="color: #0000ff;">throw</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>     <span style="color: #0000ff;">finally</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>         Transaction.Current = originalTransaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>         transaction.Dispose();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span> }</pre><!--CRLF--></div></div>
<p>输出结果（将余额恢复成5000）：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">帐户<span style="color: #006080;">"Foo"</span>的当前余额为：￥5000</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">转帐失败，错误信息：帐户ID不存在</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">帐户<span style="color: #006080;">"Foo"</span>的当前余额为：￥5000</pre><!--CRLF--></div></div>
<p>下一篇中我们将重点介绍<a title="DependentTransaction Class" href="http://msdn2.microsoft.com/ms149663.aspx" target="_blank">DependentTransaction</a>和<a title="TransactionScope Class" href="http://msdn2.microsoft.com/h5w5se33.aspx" target="_blank">TransactionScope</a>。</p>
<p>&nbsp;</p>
<p><strong></strong><p><strong>分布式事务系列:<br /></strong><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html">谈谈分布式事务之一：SOA需要怎样的事务控制方式</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[下篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html">谈谈分布式事务之三: System.Transactions事务详解[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html">谈谈分布式事务之三: System.Transactions事务详解[下篇]</a></p><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html"></a>
</p><div id="MySignature">作者：<a href="http://artech.cnblogs.com/" target="_blank">Artech</a> <br />出处：<a href="http://artech.cnblogs.com/" target="_blank">http://artech.cnblogs.com</a> <br />本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </div><img src="http://www.cnblogs.com/artech/aggbug/1660088.html?type=1" width="1" height="1" alt=""/><p>评论: 4　<a href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>谈谈分布式事务之二：基于DTC的分布式事务管理模型[下篇]</title><link>http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Wed, 27 Jan 2010 14:41:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html</guid><description><![CDATA[<p>阅读: 1285 评论: 10 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-01-27 22:41 <a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html" target="_blank">原文链接</a></p><h1>[续<a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html" target="_blank">上篇</a>]当基于LTM或者KTM的事务提升到基于DTC的分布式事务后，DTC成为了本机所有事务型资源管理器的管理者；此外，当一个事务型操作超出了本机的范围，出现了跨机器的调用后，本机的DTC需要于被调用者所在机器的DTC进行协助。上级对下级（包括本机DTC对本机所有资源管理器，以及上下级DTC）的管理得前提是下级在上级那里登记，即事务登记（Transaction Enlist）。所有事务参与者，包括所有资源管理器和事务管理器（即DTC）在进行了事务等级完成之后形成了一个树形的层级结构，该结构的形成是后续的事务提供成为可能，因此我们将其称之为事务提交树（Transaction Commit Tree）。 </h1> <h1><font size="4"><strong>一、事务登记（Transaction Enlisting）和事务提交树（Transaction Commit Tree）</strong></font></h1> <p>事务登记的目的在于建立起事务参与者（只要指资源管理器和事务管理器DTC）之间的关系，促进相互之间的协作。我们先来看看整个事务登记是如何进行的，整个事务登记流程大致如<strong>图1</strong>所示。 </p> <p align="center"><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/DTC_1370F/image_6.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/DTC_1370F/image_thumb_2.png" width="568" border="0" height="161" /></a> </p> <p align="center"><strong>图1 事务登记的流程</strong></p> <p><strong>图1</strong>所示的事务涉及到部署与两台机器（Machine A和Machine B）上两个服务之间的交互，事务由Service初始化，在调用Service2的时候被传播到Machine B，从而将分布于两台机器的资源管理器纳入到同一个事务之中。接下来，我们对整个流程进行详细介绍。 </p> <p>首先，Service A开始一个新的事务，并将其最为当前执行上下文的环境事务（Ambient Transaction）。当Service A调用本机的资源管理器的时候，会将该资源管理器纳入到本事务之中（对于我们后续要介绍的System.Transactions事务，像SQL Server、Oracle以及MSMQ等资源管理器都能够自动感知到当前的环境事务）。此时，资源管理器（RM）向本机的DTC进行事务登记，从此DTC和资源管理器之间建立起了上下级关系。 </p> <p>当Service A在调用Service B的时候，会将当前事务的一些信息，比如分布式事务的ID以及关于本机DTC相关信息，封装在消息中（一般是SOAP报头）向对方传递。当Service B接受到服务调用请求消息，会将事务相关的信息提取出来在本地重建事务，并将其作为当前的环境事务，该事务和原事务具有相同的ID。同时，根据得到的关于Machine A的DTC相关信息，让本机的DTC对Machine A的DTC进行事务登记，进而使两台机器的DTC确立了上下级关系。 </p> <p>和Service A访问本机的资源管理器一样，Machine B的资源管理器被Service B调用并被纳入当前事务的时候，会向本机DTC进行事务登记。 </p> <p>当上面所述的事务登记流程结束后，参与整个分布式事务的DTC和资源管理器形成了如<strong>图2</strong>所示的树形层次结构，由于该结构的构建主要是为了后面对整个事务的提交服务的，所以我们一般将其称为事务提交树（Transaction Commit Tree）。事务提交树的根为事务初始化服务所在机器的DTC，在整个事务提交过程中，它是总的协调者，又被称为全局提交协调器（GCC：Global Commit Coordinator ）。资源管理器充当事务提交树的叶子节点，它们的父节点为本机的DTC。分布于不同机器的DTC按照事务传播的路径形成上下级关系。 </p> <p align="center"><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/DTC_1370F/image_4.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/DTC_1370F/image_thumb_1.png" width="576" border="0" height="259" /></a> </p> <p align="center"><strong>图2 事务提交树</strong> </p> <p>事务提交树的构建使得对分布式事务的提交成为可能，分布式事务的提交采用两阶段协议实现，接下来我们详细介绍基于两阶段提交协议的事务提交机制。 </p> <h1><font size="4"><strong>二、基于两阶段提交（2PC：Two-Phase Commit）协议的事务提交机制</strong></font></h1> <p>不同于基于单一资源管理器的本地事务，在一个分布式环境中时实现一个涉及到多个资源管理器的分布式事务，实现事务的ACID四大属性，要麻烦得多。当事务初始化服务（应用或者组件，为了更佳贴近WCF，我们都称服务）完成所有相关的操作，决定提交该事务。对于分布式事务的提交，最终的结果有两个：如果所有的操作能够顺利完成，需要持久化的数据被相应的资源管理器写入到目标资源；如果任何一个环节失败，所有持久化资源管理器将数据恢复到原来的状态。分布式事务的整个提交过程，采用两阶段提交（2PC：Two-Phase）Commit协议完成。顾名思义，&#8220;两阶段提交&#8221;意味整个整个事务提交阶段分两个阶段，我们现在就来详细介绍分别在这两个阶段中，都在做些什么。 </p> <p><font face="楷体"><strong>注：</strong>在事务初始化服务决定提交事务之前，任何一个参与者均可以中止（Abort）该事务，任何一个参与者对事务的中止都将导致整个分布式事务的回滚。</font> </p> <h3>1、第一阶段（Phase I）：准备（Prepare）阶段</h3> <p>在第一个阶段，作为根节点的DTC沿着事务提交树的路径，向所有事务的参与者发起请求，要求它们对本地事务的结果进行投票。被请求的参与者将本地事务结果返回给自己的上级，对于资源管理器，自己的上级就是本机的DTC；如果自己本身就是DTC，那么自己得上级就是位于事务提交树父节点的DTC。根据具体事务操作执行的情况，参与者投票的类型包括如下三种： </p> <ul> <li><strong>就绪（Prepared）：</strong>参与者同意对事务的提交，并承诺在接收到真正的提交请求后完成本地的提交任务；  </li><li><strong>只读（Read-only）：</strong>参与者同意对事务的提交，但是不希望接收真正的事务提交请求；  </li><li><strong>中止（Aborted）：</strong>参与者要求中止事务。</li></ul> <p>对于一个非根节点DTC来说，当它从父节点接收到标准的&#8220;准备&#8221;请求后，会立即将该请求沿着事务提交树发送给自己的下级（本机的资源管理器和下级DTC），然后根据从下级接收的所有投票结果，计算出自己投票的结果。具体的算法是：如果所有的投票结果都是&#8220;就绪&#8221;和&#8220;只读&#8221;，对应的结果是&#8220;提交&#8221;，反之，如果任何一个投票结果是&#8220;中止&#8221;，则最终的结果就是&#8220;中止&#8221;，换句话说，任何一个事务参与者具有一票否决权最后。最后，DTC将计算出来的投票结果反馈给自己的上级。 </p> <p>当根节点DTC接收到隶属于自己的所有资源管理器和下级DTC的投票结果后，采用于上面一样的算法决定整个分布式事务的最终结果。当根节点DTC决定了事务最终的结果后，整个提交过程进入第二阶段。 </p> <p><font face="楷体"><strong>注：</strong>我们可以设置事务的超时时限，如果根节点DTC在该时限内没有介绍到所有参与者的投票请求，会对整个分布式事务做出回滚的决定。</font> </p> <h3>2、第二阶段（Phase II）：提交（Commit）或中止（Abort）</h3> <p>作为事务提交树根节点的DTC根据最终的事务结果，对整个事务进行最终的提交或者中止操作。同样是沿着事务提交树的路径，提交或者中止请求被广播出去。相应的资源管理器根据从本机DTC获得的请求，实施最终的提交或者恢复操作。当事务参与者完成了各自就的任务后，类似于第一个阶段的投票，会讲执行的结果沿着事务提交树逆向回馈给作为根节点的DTC。 </p> <p>根节点DTC只有接收到所有事务参与者的基于各自事务处理的回复，才能确保整个事务被成功提交或者回滚。那么如果事务的参与者完成了第一阶段的投票，网络断开，那将如何呢？这就涉及到对未决（In-Doubt）事务的处理。 </p> <h3>3、未决（In-Doubt）事务的处理</h3> <p>对于某个分布式事务的参与者（DTC或者资源管理器）来说，在第一阶段向上级（事务提交树的父节点）投票表明提交就绪（Prepared）之后，直到它接收到根节点DTC最终的提交或者回滚的请求，它并不知晓本地事务的结果。在这期间，如果出现当机并重启，本地的事务处于一种&#8220;未决（In-Doubt）&#8221;状态。未决事务仅仅出现在非根节点DTC所在的机器。分布式事务采用如下的机制处理未决事务。 </p> <p>当重启后，对于本机的所有未决事务，DTC会向上级DTC发送查询请求，获取每一个事务最终的结果（提交还是中止）。如果上级也不能决定事务的结果，那么请求会沿着事务提交树不断向上（沿着根的方向）发送，直到得到一个明确的答复（不管怎样，位于根节点的全局提交协调器总是清楚事务的结果的）。 </p> <p>此外，当下级DTC向自己发送相同的查询请求的时候，该DTC会讲获取到的结果回复给它们。如果未决事务存在的时间太长，系统管理者可以强制提交或者中止该事务。 </p> <h3>4、单阶段提交（SPC: Single-Phase Commit）优化</h3> <p>对于事务最终结果（提交或者中止）的决策者来说，如果它具有了不止一个下级，那么采用基于投票机制的两阶段提交协议唯一选择。但是如果仅仅具有一个唯一的下级呢，这种投票机制就没有必要了。在这种情况下，根节点DTC采用一种优化的协议来完成整个事务的提交，我们称之为单阶段提交（SPC：Single-Phase Commit）。 </p> <p>顾名思义，2PC意味着整个事务提交分成两个阶段，SPC则表示将其所短为一个阶段。整个流程很简单，如果根节点DTC仅仅只有一个登记的事务参与者（本机资源管理器或者下级DTC），而不管这个下级自身具有几个下级，它不会像2PC一样先向下级发送&#8220;准备&#8221;请求，而是直接发送提交请求，我们将这个请求成为单阶段提交（SPC）请求。接收到SPC请求的参与者，如果是资源管理器，则直接提交本地事务，并将最终结果（成功提交或者失败中止）反馈给这个跟节点DTC。 </p> <p>如果SPC请求的接收者是DTC，那么会根据隶属于自己的下级的数量选择相应的提交策略。具体做法和根节点DTC提交策略的选择方式一样：如果自己具有唯一一个下级，则采用SPC，反之采用2PC。 </p> <p>也就是说，不仅仅是根节点DTC可以选择SPC提交事务，任何具有单一下级的DTC均可以采用SPC。但是，非根节点DTC只有在接收到SPC请求的情况下，才能选择通过SPC提交事务。如<strong>图3</strong>给出了两颗事务提交树（图中忽略掉资源管理器，每个节点代表DTC），对于左边的树，因为根节点A和下级B均只有一个唯一的下级，所以A和B均采用SPC，C具有两个下级，则采用2PC。而对于右边的树，因为根节点本身具有两个下级，决定了所有的节点均采用2PC，即使是对于只有一个下级的B和C。 </p> <p align="center"><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/DTC_1370F/image_2.png" target="_blank"><img style="border-width: 0px; display: inline;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/DTC_1370F/image_thumb.png" width="594" border="0" height="186" /></a> </p> <p align="center">&nbsp;<strong>图3 DTC对SPC和2PC的选择</strong>&nbsp;</p> <p>我们我们介绍整个Windows平台基于DTC的分布式事务管理模型，接下来的一篇中，我将会详细介绍基于System.Transactions事务的编程。</p><p>&nbsp;</p><strong></strong><p><strong>分布式事务系列:<br /></strong><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html">谈谈分布式事务之一：SOA需要怎样的事务控制方式</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[下篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html">谈谈分布式事务之三: System.Transactions事务详解[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html">谈谈分布式事务之三: System.Transactions事务详解[下篇]</a></p><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html"></a> <div id="MySignature">作者：<a href="http://artech.cnblogs.com/" target="_blank">Artech</a> <br />出处：<a href="http://artech.cnblogs.com/" target="_blank">http://artech.cnblogs.com</a> <br />本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </div><img src="http://www.cnblogs.com/artech/aggbug/1657926.html?type=1" width="1" height="1" alt=""/><p>评论: 10　<a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>谈谈分布式事务之二：基于DTC的分布式事务管理模型[上篇]</title><link>http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Wed, 27 Jan 2010 13:42:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html</guid><description><![CDATA[<p>阅读: 1287 评论: 5 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-01-27 21:42 <a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html" target="_blank">原文链接</a></p><p>通过<a href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html" target="_blank">上一篇</a>的介绍，我们知道了SOA真正需要的是一个能够协调服务操作直接（通过服务自身访问的资源）或者间接（通过被调用服务访问的资源）访问的所有资源的分布式事务管理系统，这是一个复杂的架构体系。WCF，作为Windows平台下基于SOA的分布式框架，对分布式事务提供全面的支持。不过，WCF并不是另起炉灶，而是充分地利用了Windows现有的事务控制基础架构。本节着重讨论Windows事务处理模型，首先来看看在这个模型中各个事务参与者各自扮演怎样的角色。 </p> <p>对于所有的事务参与者，按照各自在整个事务生命周期各个阶段所承担的职能，大致扮演着如下三种角色： </p> <ul> <li><strong>应用（Application）、服务（Service）或者组件（Component）：</strong>代表用户程序，或者是承载着某功能的服务（Service）或者组件（Component）；  </li><li><strong>资源管理器（RM：Resource Manager）:</strong>代表用于管理具体事务型资源的软件程序，比如数据库或者队列（MSMQ）等；  </li><li><strong>事务管理器（TM： Transaction Manager）:</strong>代表管理整个事务的中间件程序，为应用和资源管理器提供基本的事务控制服务。</li></ul> <h1><font size="4"><strong>一、应用（Application）、服务（Service）和组件（Component）</strong></font></h1> <p>事务最终为用户程序、服务和组件服务的，后者利用了事务这种特殊的机制将一组相关的操作作为一个不可分割的整体来执行，从而确保了数据的一致性。在整个模型中，应用（服务或者应用，为了叙述简练，后续部分关于应用、服务和组件都简称为应用）主要负责如下一些事务相关的任务： </p> <ul> <li><strong>开始事务：</strong>事务开始的驱动者总是应用，但是并不是所有的应用都会开始一个新的事务，只有最初的应用才才是事务的开启者；  </li><li><strong>事务的奉送（Marshaling）和传播（Propagation）：</strong>将应用的本地事务封送、传播给另一个应用或者资源管理器；  </li><li><strong>提交事务：</strong>事务的开启者同时也是事务最终的提交者，当事务相关的操作顺利完成后，最初开启事务的应用会提交该事务。</li></ul> <h1><font size="4"><strong>二、资源管理器（RM：Resource Manager）</strong></font></h1> <p>在事务控制模型中，不论是应用还是资源管理器都不是直接地访问具体的事务型资源，而是通过一个中介间接地对目标资源进行操作，这个中介就是资源管理器。按照目标资源是否可被持久化，可以将相应的资源管理器分为如下两类： </p> <ul> <li><strong>持久化资源管理器（Durable Resource Manager）：</strong>用于管理持久化资源，比如数据库和MSMQ，当事务回滚得时候，具有可恢复性（Recovery）；  </li><li><strong>易失资源管理器（Volatile Resource Manager）：</strong>用于管理像内存数据这样的不会被持久化的易失资源，易失资源不具有可以恢复性。</li></ul> <p>在后面介绍的实现分布式事务的两阶段提交（2PC： Two-Phase Commit）协议中，对于这两种不同的资源管理器，采用不同的登记（Enlist）方式。总的来说，资源管理器在整个事务模型中主要承担如下几种职能： </p> <ul> <li>帮助应用实现对目标资源的操作；  </li><li>注册到相应的事务管理器，以便事务回滚得时候可以从事务管理器中接收到恢复请求，实现对数据的恢复；  </li><li>向相应的事务管理器报告本地事务的结果；</li></ul> <h1><font size="4"><strong>三、事务管理器(Transaction Manager)</strong></font></h1> <p>事务管理器是整个事务控制模型的核心和枢纽，是它控制着事务的所有参与者，协调整个事务从开始到完成的所有相关处理流程。事务管理器为应用和资源管理器提供一系列核心的事务性的服务，实现事务的开始、提交和回滚。Windows提供了三种不同的事务管理器，我们现在对它们进行逐个介绍。 </p> <h3>1、轻量级事务管理器（LTM: Lightweight Transaction Manager）</h3> <p>正如其名称隐含的意思,轻量级事务管理器（以下简称LTM）具有最小的负载,是性能最高的事务管理器。LTM的作用范围仅限于开启事务的应用程序域（AppDomain）中，并且登记到事务中的持久化资源（Durable Resource）数量不能超过一个。 </p> <p>一般地，被开启的事务就由LTM管理，如果事务涉及到跨应用程序域的操作，当前的事务回被奉送、传播到另一个执行上下文中，此时事务将脱离LTM的管辖。此外，基于LTM的事务中可以同时登记（Enlist）多个易失型资源（Volatile），但是仅仅允许登记唯一一个持久化资源。当第二个持久化资源被登记到当前事务中，该事务也将脱离LTM的管辖。 </p> <p>并不是所有的持久化资源都可以登记到LTM，实际上到目前为止，能够登记到LTM这么一个高性能的事务管理器的事务型资源仅仅限于SQL Server 2005和SQL Server 2008，即使是同属于Windows平台下SQL Server 2000和MSMQ均不支持LTM，更不用说Oracle和DB2。我们希望微软能够和其他的厂商进行合作，让第三方开发的事务型资源也能利用LTM性能的优势。 </p> <h3>2、内核事务管理器（KTM：Kernel transaction Manager）</h3> <p>内核事务管理器（以下简称KTM）在Windows Vista中被引入，并被用于后续的Windows Server 2008和Windows 7。引入KTM的主要的目的在于实现将文件管理和注册表管理纳入事务的范畴。借助于KTM，我们可以以事务的方式操作NTFS文件系统下的文件资源，以及注册表资源。我们将支持事务的文件系统和注册表成为事务型的文件系统（TxF）和事务型注册表（TxR）。 </p> <p>之所以被称为内核事务管理器，使因为基于KTM的事务控制引擎运行在内核模式（Kernel Mode）,而不是用户模式（User Mode）下。和LTM一样，KTM对易失型事务资源没有限制，却至于单一的持久化事务资源被涉及。 </p> <p>从上面的介绍我们不难看出，无论是LTM还是KTM，其管辖范围仅限于本地事务，对于分布式事务却无能为力。分布式事务依赖于一个更为强大的事务管理器，就是我们接下来着重介绍的分布式事务协调器。 </p> <h3>3、分布式事务协调器（DTC：Distributed Transaction Coordinator）</h3> <p>对于分布式事务协调器，我们大都简称为DTC，或者MS DTC，以下我们直接简称DTC。DTC用于管理跨边界（跨应用程序域、进程、机器以至跨网络）执行的分布式事务，它采用相应的事务管理协议，比如Ole-Tx和WS-Atomic Transaction（WS-AT），协调一个分布式事务中的所有参与者。 </p> <p>每一台机器上具有一个唯一的DTC，事务涉及的承载于某台机器的所有事务型资源均由当前机器的DTC管理。当事务跨越多台机器时，它们各自的DTC需要按照相应的协议相互协作，实现对整个事务的一致性管理。 </p> <h3>4、事务提升（Transaction Promotion）</h3> <p>以上我们介绍了三种不同的事务管理器类型，从功能上讲，DTC能够协调、管理一个分布式事务涉及的所有事务型资源，而不管具体的资源分布于何处。但是，由于其事务控制的复杂性（一般采用两阶段提交协议）并需要进行跨进程、跨机器甚至跨网络通信，在性能上无疑是最差的。所以，我们不可能在任何事务场景中都采用DTC，所谓&#8220;牛刀虽好、不便杀鸡&#8221;，我们应该根据事务控制的需要选择性能最高的事务管理器。 </p> <p>但是，事务是一个动态执行的操作序列，系统不可能预知完整执行整个事务所有操作后的资源登记情况，所以不可以预先为其指定一个为相应事务多身定制的事务管理器。相反地，只能在事务具体的执行过程中，动态地选择最适合当前事务执行情况的事务管理器。Windows采用事务提升的机制进行事务管理器的选择。 </p> <p>一般情况下，事务开始的时候，LTM默认被作为当前的事务管理器。随着事务操作的逐步执行，如何该事务涉及到对某个内核事务资源的访问，那么自动提升到基于KTM的事务。无论是基于LTM还是KTM的事务，在当出现如下两种情况的时候，会向基于DTC事务提升： </p> <ul> <li><strong>事务操作涉及到对多个LTM资源的访问或者访问的资源不被LTM支持：</strong>比如说，当事务应用开启两个基于SQL Server 2008（LTM事务型资源）的连接进行数据存取；或者，访问开启一个基于Oracle（非LTM事务型资源）的连接进行数据存取；  </li><li><strong>当前事务被跨应用程序域封送（Marshaling）：</strong>比如说，放一个服务调用另一个服务的时候，将当前事务进行序列化以实现向被调用服务方传播。</li></ul> <p>由于WCF的事务体系解决的是事务在服务之间的流转，以及对服务操作直接或者间接访问的所有事务型资源的协作，这样的事务时通过基于DTC的分布式事务实现的。接下来，我们就来简单讨论一下《<a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html" target="_blank">基于DTC的分布式事务实现的</a>》。 </p><p>&nbsp;</p> <p><strong></strong><p><strong>分布式事务系列:<br /></strong><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html">谈谈分布式事务之一：SOA需要怎样的事务控制方式</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[下篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html">谈谈分布式事务之三: System.Transactions事务详解[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html">谈谈分布式事务之三: System.Transactions事务详解[下篇]</a></p><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html"></a></p> <div id="MySignature">作者：<a href="http://artech.cnblogs.com/" target="_blank">Artech</a> <br />出处：<a href="http://artech.cnblogs.com/" target="_blank">http://artech.cnblogs.com</a> <br />本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </div><img src="http://www.cnblogs.com/artech/aggbug/1657875.html?type=1" width="1" height="1" alt=""/><p>评论: 5　<a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>谈谈分布式事务之一：SOA需要怎样的事务控制方式</title><link>http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Tue, 26 Jan 2010 14:57:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html</guid><description><![CDATA[<p>阅读: 1823 评论: 33 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-01-26 22:57 <a href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html" target="_blank">原文链接</a></p><p>在一个基于SOA架构的分布式系统体系中，服务（Service）成为了基本的功能提供单元，无论与业务流程无关的基础功能，还是具体的业务逻辑，均实现在相应的服务之中。服务对外提供统一的接口，服务之间采用标准的通信方式进行交互，各个单一的服务精又有效的组合、编排成为一个有机的整体。在这样一个分布式系统中某个活动（Activity）的实现往往需要跨越单个服务的边界，如何协调多个服务之间的关系使之为活动功能的实现服务，涉及到SOA一个重要的课题：服务协作（Service Coordination）。而具体来讲，一个分布式的活动可能会执行几秒钟，比如银行转帐；也可能执行几分钟、几个小时、几天甚至更长，比如移民局处理移民的申请。事务，无疑是属于短暂运行服务协作（Short-Running Service Coordination）的范畴。 </p> <h1><font size="4"><strong>一、 什么是事务（Transaction）</strong></font></h1> <p>事务提供一种机制将一个活动涉及的所有操作纳入到一个不可分割的执行单元，组成事务的所有操作只有在所有操作均能正常执行的情况下方能提交，只要其中任一操作执行失败，都将导致整个事务的回滚。简单地说，事务提供一种&#8220;要么什么都不做，要么做全套（All or Nothing）&#8221;机制。事务具有如下四个属性，根据其首字母，我们一般将其称为事务的ACID四大属性： </p> <ul> <li><strong>原子性（Atomicity）：</strong>&#8220;原子&#8221;这个词的本义就是不可分割的意思，事务的原子性的含义是：一个事务的所有操作被捆绑成一个整体，所有的操作要么全部执行，要么都不执行；  </li><li><strong>一致性（Consistence）：</strong>事务的原子性确保一个事务不会破环数据的一致性，如果事务成功提交，数据的状态是组成事务的所有操作按照事先编排的方式执行的结果，数据状态具有一致性；如果事务任何一个中间步骤出错，整个事务回滚并将数据回复到原来的状态，数据状态仍然具有一致性。所以，事务只会将数据状态从一个一致性状态转换到另一个一致性状态；  </li><li><strong>隔离性（Isolation）：</strong>从事务的外部来看，事务的一致性实现了数据在两个一致性状态之间的转换，但是从事务内部来看，组成事务的各个操作是按照一定的逻辑顺序执行的，所以数据具有位于两个一致性状态的&#8220;中间状态&#8221;。但是，这种中间状态被隔离于事务内部，对于事务外部是不可见的；  </li><li><strong>持久性（Durability）：</strong>持久性的意思是一旦成功提交，基于持久化资源（比如数据库）的数据将会被持久化，对数据的改变是永久性的。</li></ul> <p>事务最初来源于数据库管理系统（DBMS），反映的是对存储于数据库中的数据操作。除了主流的关系型数据库管理系统，比如SQL Server，Oracle和DB2等提供对事务的支持，基于事务的数据操作方式也可以应用到其他一些数据存储资源，比如MSMQ。自Windows Vista开始将文件系统（NTFS）以至于注册表纳入了事务型资源（Transactional Resource）的范畴。 </p> <h1><font size="4"><strong>二、 事务的显式控制</strong></font></h1> <p>虽然事务型资源家族成员越来越多，但是不可否认的是，数据库还是我们使用频率最高的事务型资源。对于稍微有一定经验的开发人员，应该都在存储过程（Stored Procedure）中编写过基于事务的SQL，或者编写过基于ADO.NET事务的代码，对事务的进一步介绍就从这里说起。 </p> <p><font size="3"><strong>1、SQL中的事务处理</strong></font></p> <p>无论是基于SQL Server的T-SQL，抑或是基于Oracle的PL-SQL都对事务提供了原生的支持，有意思的是T-SQL中的T本身指的就是事务（Transaction）。以T-SQL为例，我们可以通过如下三个SQL语句实现事务的启动、提交与回滚： </p> <ul> <li><strong>BEGIN TRANSACTION:</strong> 开始一个事务；  </li><li><strong>COMMIT TRANSACTION</strong><strong>：</strong>提交所有位于BEGIN TRANSACTION和COMMIT TRANSACTION之间的操作；  </li><li><strong>ROLLBACK TRANSACTION</strong><strong>：</strong>回滚所有位于BEGIN TRANSACTION和COMMIT TRANSACTION之间的操作。</li></ul> <p>我们举一个很典型的基于事务型操作的例子：银行转帐，而且这个例子将会贯穿于本章的始终。为此，我们先创建一个最为简单的用于存储帐户的数据表：T_ACCOUNT,整个表近仅仅包括三个字段（ID、NAME和BALANCE），它们分别代表银行帐号的ID、名称和余额。创建该表的T-SQL如下：</p> <div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper"> <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">TABLE</span> [dbo].[T_ACCOUNT](</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span>     [ID]        <span style="color: #0000ff;">VARCHAR</span>(50)     <span style="color: #0000ff;">PRIMARY</span> <span style="color: #0000ff;">KEY</span>,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     [NAME]      NVARCHAR(50)    <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">NULL</span>,</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     [BALANCE]   <span style="color: #0000ff;">FLOAT</span>           <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">NULL</span>)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> <span style="color: #0000ff;">GO</span></pre><!--CRLF--></div></div>
<p>银行转帐是一个简单的复合型操作，由两个基本的操作构成：存储和提取，即从一个帐户中提取相应金额出入另一个帐户。对数据完整性的要求是我们必须将这两个单一的操作纳入同一个事务。如果我们通过一个存储过程来完成整个转帐的流程，具体的SQL应该采用下面的写法：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">Procedure</span> P_TRANSFER</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span>     (</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>         @fromAccount    <span style="color: #0000ff;">VARCHAR</span>(50),</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>         @toAccount      <span style="color: #0000ff;">VARCHAR</span>(50),</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>         @amount         <span style="color: #0000ff;">FLOAT</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     )</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> <span style="color: #0000ff;">AS</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span> --确保帐户存在性</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span> <span style="color: #0000ff;">IF</span> <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">EXISTS</span>(<span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> [dbo].[T_ACCOUNT] <span style="color: #0000ff;">WHERE</span> ID = @fromAccount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>     <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>         <span style="color: #0000ff;">RAISERROR</span> (<span style="color: #006080;">'AccountNotExists'</span>,16,1) </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>         <span style="color: #0000ff;">RETURN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>     <span style="color: #0000ff;">END</span>    </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span> <span style="color: #0000ff;">IF</span> <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">EXISTS</span>(<span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> [dbo].[T_ACCOUNT] <span style="color: #0000ff;">WHERE</span> ID = @toAccount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>     <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>         <span style="color: #0000ff;">RAISERROR</span> (<span style="color: #006080;">'AccountNotExists'</span>,16,1) </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>         <span style="color: #0000ff;">RETURN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>     <span style="color: #0000ff;">END</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span> --确保余额充足性</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span> <span style="color: #0000ff;">IF</span> <span style="color: #0000ff;">NOT</span> <span style="color: #0000ff;">EXISTS</span>(<span style="color: #0000ff;">SELECT</span> * <span style="color: #0000ff;">FROM</span> [dbo].[T_ACCOUNT] <span style="color: #0000ff;">WHERE</span> ID = @fromAccount <span style="color: #0000ff;">AND</span> BALANCE &gt;= @amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>     <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>         <span style="color: #0000ff;">RAISERROR</span> (<span style="color: #006080;">'LackofBalance'</span>,16,1)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>         <span style="color: #0000ff;">RETURN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span>     <span style="color: #0000ff;">END</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum26">  26:</span> --转帐</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum27">  27:</span> <span style="color: #0000ff;">BEGIN</span> <span style="color: #0000ff;">TRANSACTION</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum28">  28:</span>     <span style="color: #0000ff;">UPDATE</span>     [dbo].[T_ACCOUNT] <span style="color: #0000ff;">SET</span> BALANCE = BALANCE - @amount <span style="color: #0000ff;">WHERE</span> ID = @fromAccount</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum29">  29:</span>     <span style="color: #0000ff;">IF</span> <span style="color: #cc6633;">@@ERROR</span> &lt;&gt; 0 </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum30">  30:</span>         <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum31">  31:</span>             <span style="color: #0000ff;">ROLLBACK</span> <span style="color: #0000ff;">TRANSACTION</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum32">  32:</span>         <span style="color: #0000ff;">END</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum33">  33:</span>     <span style="color: #0000ff;">UPDATE</span>     [dbo].[T_ACCOUNT] <span style="color: #0000ff;">SET</span> BALANCE = BALANCE + @amount <span style="color: #0000ff;">WHERE</span> ID = @toAccount</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum34">  34:</span>     <span style="color: #0000ff;">IF</span> <span style="color: #cc6633;">@@ERROR</span> &lt;&gt; 0 </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum35">  35:</span>         <span style="color: #0000ff;">BEGIN</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum36">  36:</span>             <span style="color: #0000ff;">ROLLBACK</span> <span style="color: #0000ff;">TRANSACTION</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum37">  37:</span>         <span style="color: #0000ff;">END</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum38">  38:</span> <span style="color: #0000ff;">COMMIT</span> <span style="color: #0000ff;">TRANSACTION</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum39">  39:</span> <span style="color: #0000ff;">GO</span></pre><!--CRLF--></div></div>
<p><font size="3"><strong>2、 ADO.NET事务控制</strong></font></p>
<p>无论是T-SQL，还是PL-SQL，抑或是其他数据库管理系统对标准SQL的扩展，不仅仅是提供基于标准SQL的DDL（Data Definition Language）和DML（Data Manipulation Language），还提供了对函数、存储过程和流程控制的支持。SQL Server至2005起，甚至实现了与CLR（Common Language Runtime）的集成，使开发人员可以使用任何一种.NET语言编写编写函数或者存储过程。毫无夸张地说，你可以通过SQL实现任何业务逻辑。 </p>
<p>但是，在大多数情况我们并不这么做，我们更多地还是将SQL作为最基本的数据操作语言在使用。对于.NET开发者来说，我们还是习惯将复杂的逻辑和流程控制实现在通过C#或者VB.NET这样的面相对象编程语言编写的程序中。究其原因，我觉得主要有两点： </p>
<ul>
<li><strong>面相对象的语言更能容易地实现复杂的逻辑：</strong>较之SQL这种基于集合记录的语言，面相对象的语言更加接近于我们真实的世界，通过面相对象的方式模拟具体的逻辑更加贴近于人类的思维方式。此外，通过面相对语言本身的一些特性，我们可以更加容易地应用各种设计模式和思想； 
</li><li><strong>将太多逻辑运算的执行放在数据库中不利于应用的扩展：</strong>从部属的角度来讲，数据操作运算负载到具体的服务器中，以一个典型的分布式Web应用为例，Web服务器（承载Web应用）、应用服务器（承载各种服务）和数据库服务器均可以承载最终对逻辑的运算。但是，从可扩展性（或者可伸缩性）上考虑，将主要的计算放在前两者比放在数据库更具优势。如果我们将密集的运算（这种运算需要占用更多的CPU时间和内存）迁移到Web服务器或者应用服务器，我们可以通过负载均衡（Load Balance）将其分流到多台服务器上面，这个服务器机群可以根据负载情况进行动态地配置。但是，数据库服务器对负载均衡的支持就不那么容易。</li></ul>
<p>正因为如此，对于事务的控制，较之采用SQL的实现方式，我们使用得最多的还是采用基于面相对象语言编程的方式。对于.NET开发人员，我们可以直接利用ADO.NET将基于单个数据库连接的多个操作纳入同一个事务之中。同样以上面的银行转帐事务为例，这次我们将整个转帐作为一个服务（BankingService）的一个操作（Transfer）。下面的代码通过一种与具体数据库类型无关的ADO.NET编程模式实现了整个银行转帐操作，最终的转帐通过调用一个存储过程实现：</p>
<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
<div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet"><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> BankingService : IBankingService</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     <span style="color: #008000;">//其他操作</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Transfer(<span style="color: #0000ff;">string</span> fromAccountId, <span style="color: #0000ff;">string</span> toAccountId, <span style="color: #0000ff;">double</span> amount)</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>         <span style="color: #0000ff;">string</span> connectionStringName = <span style="color: #006080;">"BankingDb"</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         <span style="color: #0000ff;">string</span> connectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         <span style="color: #0000ff;">string</span> providerName = ConfigurationManager.ConnectionStrings[connectionStringName].ProviderName;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         DbProviderFactory dbProviderFactory = DbProviderFactories.GetFactory(providerName);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>         <span style="color: #0000ff;">using</span> (DbConnection connection = dbProviderFactory.CreateConnection())</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>         {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             connection.ConnectionString = connectionString;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>             DbCommand command = connection.CreateCommand();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>             command.CommandText = <span style="color: #006080;">"P_TRANSFER"</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>             command.CommandType = CommandType.StoredProcedure;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>             DbParameter parameter = dbProviderFactory.CreateParameter();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>             parameter.ParameterName = BuildParameterName(<span style="color: #006080;">"fromAccount"</span>);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>             parameter.Value = fromAccountId;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>             command.Parameters.Add(parameter);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>             parameter = dbProviderFactory.CreateParameter();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>             parameter.ParameterName = BuildParameterName(<span style="color: #006080;">"toAccount"</span>);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>             parameter.Value = toAccountId;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span>             command.Parameters.Add(parameter);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum26">  26:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum27">  27:</span>             parameter = dbProviderFactory.CreateParameter();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum28">  28:</span>             parameter.ParameterName = BuildParameterName(<span style="color: #006080;">"amount"</span>);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum29">  29:</span>             parameter.Value = amount;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum30">  30:</span>             command.Parameters.Add(parameter);</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum31">  31:</span>&nbsp; </pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum32">  32:</span>             connection.Open();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum33">  33:</span>             <span style="color: #0000ff;">using</span> (DbTransaction transaction = connection.BeginTransaction())</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum34">  34:</span>             {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum35">  35:</span>                 command.Transaction = transaction;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum36">  36:</span>                 <span style="color: #0000ff;">try</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum37">  37:</span>                 {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum38">  38:</span>                     command.ExecuteNonQuery();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum39">  39:</span>                     transaction.Commit();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum40">  40:</span>                 }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum41">  41:</span>                 <span style="color: #0000ff;">catch</span></pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum42">  42:</span>                 {</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum43">  43:</span>                     transaction.Rollback();</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum44">  44:</span>                     <span style="color: #0000ff;">throw</span>;</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum45">  45:</span>                 }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum46">  46:</span>             }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum47">  47:</span>         }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum48">  48:</span>     }</pre><!--CRLF--><pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum49">  49:</span> }</pre><!--CRLF--></div></div>
<p><font face="楷体"><strong>注：</strong>为了使上面一段代码能够同时用于不同的数据库类型，比如SQL Server和Oracle，我通过提取连接字符串配置中的数据库提供者（DbProvider）名称，借此创建相应的DbProviderFactory对象。所有ADO.NET对象，包括DbConnection、DbCommand、DbParameter以及DbTransaction均通过DbProviderFactory创建，所以并不和具体的数据库类型绑定在一起。此外，基于不同数据库类型的存储过程的参数命名各不相同，比如 SQL Server的参数会添加&#8221;@&#8221;前缀，为此我将对参数名称的解析实现在一个单独的方法（BuildParameterName）之中。</font> </p>
<p><font size="3"><strong>3、事务的显式控制限定于对单一资源的访问</strong></font></p>
<p>通过在SQL中进行事务的控制，只能将基于某一段SQL语句的操作纳入到一个单一的事务中；如果采用基于ADO.NET的数据控制，被纳入到同一个事务的操作仅仅限于某个数据库连接。换句话说，上面介绍的这两种对事务的显式控制仅仅限于对单一的本地资源的控制。 </p>
<p>我们将事务的概念引入服务，倘若我们将一个单一的服务操作作为一个事务，如果采用上述的显式事务控制的方式，那么整个服务操作只能涉及一个单一的事务资源。服务于存取的资源关系如<strong>图1</strong>所以。 </p>
<p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/SOA_142BD/image_2.png" target="_blank"><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/SOA_142BD/image_thumb.png" width="527" border="0" height="128" /></a></p>
<p align="center"><strong>图1 本地事务对单一资源的控制</strong></p>
<p>上述的这种基于某个服务单一本地资源的访问的事务，被称为本地事务（Local Transaction），在一个基于SOA分布式应用环境下，我们需要的同时能将多个资源、多个服务进行统一协作的分布式事务（Distributed Transaction）。接下来，我们来介绍几种典型的分布式事务应用的场景。 </p>
<h1><font size="4"><strong>三、分布式事务（Distributed Transaction）应用场景</strong></font></h1>
<p>对于一个分布式事务（Distributed Transaction）来讲，事务的参与者分布于网络环境中的不同的节点。也就是说，我们可以将多个事务资源纳入到一个单一的事务之中，并且这些事务资源可以分布到不同的机器上。这些承载分布式资源的机器可能是出于同一个网络中，也可能处于不同的网络中。甚至说，某个事务资源本质上就是一个通过HTTP访问的单纯的Internet资源。 </p>
<p>站在SOA的角度来看分布式事务，意味着将服务的某个服务操作视为一个单一的事务。该服务操作可能会访问不止一个事务资源（比如访问两个不同的数据库服务器），也可能调用另一个服务。下面介绍了三个典型的分布式事务应用场景，先从最简单的说起。 </p>
<p><font size="3"><strong>1、将对多个资源的访问纳入同一事务</strong></font></p>
<p>第一个分布式事务应用场景最简单，即一个服务操作并不会调用另一个服务，但是服务操作涉及到对多个事务资源的访问。当一个服务操作访问不同的数据库服务器，比如两台SQL Server，或者一台SQL Server和一台Oracle Server；当一个服务操作访问的是相同数据库，但是相应的数据库访问时基于不同的数据连接；当一个服务操作处理访问数据库资源，还需要访问其他份数据库的事务资源，就需要采用分布式事务来对所有的事务参与者进行协作了。<strong>图2</strong>反映了这样的分布式应用场景。 </p>
<p><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/SOA_142BD/image_4.png" target="_blank"><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/SOA_142BD/image_thumb_1.png" width="515" border="0" height="145" /></a> </p>
<p align="center"><strong>图2 单一服务对多个事务资源的访问</strong> </p>
<p><font size="3"><strong>2、将对各个服务的调用纳入同一事务</strong></font></p>
<p>对于上面介绍的分布式应用场景，尽管一个服务操作会访问多个事务资源，但是毕竟整个事务还是控制在单一的服务内部。如果一个服务操作需要调用另外一个服务，这是的事务就需要跨越多个服务了。在这种情况下，起始于某个服务的事务在调用另外一个服务的时候，需要以某种机制流转到另外一个服务，以使被调用的服务访问的资源自动加入进来。<strong>图3</strong>反映了这样一个跨越多个服务的分布式事务。 </p>
<p align="center"><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/SOA_142BD/image_6.png" target="_blank"><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/SOA_142BD/image_thumb_2.png" width="522" border="0" height="142" /></a>&nbsp;<strong>图3 跨越多个服务的事务</strong></p>
<p><font size="3"><strong>3、 将对多个资源和服务的访问纳入同一个事务</strong></font></p>
<p>如果将上面这两种场景（一个服务可以调用多个事务资源，也可以调用其他服务）结合在一起，对此进行延伸，整个事务的参与者将会组成如<strong>图4</strong>所示的树形拓扑结构。在一个基于分布式事务的服务调用中，事务的发起者和提交均系同一个，它可以是整个调用的客户端，也可以是客户端最先调用的那个服务。 </p>
<p align="center"><a href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/SOA_142BD/image_8.png" target="_blank"><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/SOA_142BD/image_thumb_3.png" width="530" border="0" height="212" /></a>&nbsp;<strong>图4 基于SOA分布式事务拓扑结构</strong> </p>
<p>较之基于单一资源访问的本地事务，分布式事务的实现机制要复杂得多。Windows平台提供了基于DTC分布式事务基础架构，<a href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html" target="_blank">下一篇文章</a>中我将对针对该架构模型详细介绍分布式事务时如何工作的。 </p><p>&nbsp;</p><strong></strong><p><strong>分布式事务系列:<br /></strong><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html">谈谈分布式事务之一：SOA需要怎样的事务控制方式</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657875.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html">谈谈分布式事务之二：基于DTC的分布式事务管理模型[下篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/30/1660088.html">谈谈分布式事务之三: System.Transactions事务详解[上篇]</a><br /><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/31/1660356.html">谈谈分布式事务之三: System.Transactions事务详解[下篇]</a></p><a target="_blank" href="http://www.cnblogs.com/artech/archive/2010/01/27/1657926.html"></a>
<div id="MySignature"><a href="http://artech.cnblogs.com/" target="_blank"></a> <br /><a href="http://artech.cnblogs.com/" target="_blank"></a> <br /></div><p>作者：Artech出处：http://artech.cnblogs.com本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </p><img src="http://www.cnblogs.com/artech/aggbug/1657102.html?type=1" width="1" height="1" alt=""/><p>评论: 33　<a href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/01/26/1657102.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>WCF技术剖析之三十：一个很有用的WCF调用编程技巧[下篇]</title><link>http://www.cnblogs.com/artech/archive/2010/01/08/1642607.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Fri, 08 Jan 2010 12:49:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/01/08/1642607.html</guid><description><![CDATA[<p>阅读: 1532 评论: 19 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-01-08 20:49 <a href="http://www.cnblogs.com/artech/archive/2010/01/08/1642607.html" target="_blank">原文链接</a></p><p>在<a href="http://www.cnblogs.com/artech/archive/2010/01/04/1639149.html" target="_blank">《上篇》</a>中，我通过使用Delegate的方式解决了服务调用过程中的异常处理以及对服务代理的关闭。对于《<a target="_blank" href="http://www.china-pub.com/46907&amp;ref=ps">WCF技术剖析（卷1）</a>》的读者，应该会知道在第7章中我通过类似于AOP的方式解决了相似的问题，现在我们来讨论这个解决方案。</p>  <p>通过《<strong><a target="_blank" href="http://www.cnblogs.com/artech/archive/2009/07/04/1516908.html">服务代理不能得到及时关闭会有什么后果?</a></strong>》的介绍，我们知道了及时关闭服务代理的重要意义，并且给出了正确的编程方式。如果严格按照上面的编程方式，就意味着对于每一个服务调用，都要使用相同的代码进行异常处理和关闭或中断服务代理对象。按照我个人的观点，一个应用程序的每一个角落若充斥着相同的代码片断，这是一种很不好的设计。设计的目的在于<strong>实现代码的重用（Reuse），绝非代码的重复（Duplicate）</strong>。</p>  <p>所以现在我们的目的是将重复使用的代码进行单独维护，在使用到的地方进行重用。思路是这样：通过一个对象实现对客户端进行服务访问的方法调用的劫持，在该对象的内部实现真正的方法调用、服务代理关闭或中断，以及异常处理。这实际上是一种基于AOP的解决方案，在这里通过自定义真实代理（<a target="_blank" title="RealProxy Class" href="http://msdn2.microsoft.com/f59atft6.aspx">RealProxy</a>）的方式来实现服务调用的AOP，这也是为何在本章的开始会花如此多的笔墨介绍真实代理和透明代理的一个重要原因。</p>  <p>下图所示的顺序图（Sequence Diagram）揭示了具体实现的原理：在定义的<a target="_blank" title="RealProxy Class" href="http://msdn2.microsoft.com/f59atft6.aspx">RealProxy</a>（ServiceRealProxy）中实现了服务调用、异常处理和信道关闭或中断。客户端代码进行服务调用完全是通过自定义真实代理ServiceRealProxy的透明代理进行的，所以所有的方法调用都会直接分发给ServiceRealProxy对象。ServiceRealProxy根据当前方法调用的上下文（比如参数、MethodBase等）构建ChannelFactory&lt;T&gt;对象并创建真正的服务代理对象。然后ServiceRealProxy借助创建出来的服务代理进行真正的服务调用，如果服务调用正常完成，则调用Close方法关闭服务代理，如果在调用过程中抛出<a target="_blank" title="CommunicationException Class" href="http://msdn2.microsoft.com/ms405965.aspx">CommunicationException</a>和<a target="_blank" title="TimeoutException Class" href="http://msdn2.microsoft.com/cke1faa2.aspx">TimeoutException</a>这两个异常，则调用Abort方法强行中断服务代理。最后，将服务调用的结果或抛出的异常通过<strong>TransparentProxy</strong>返回给客户端代码。</p>  <p><a target="_blank" href="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/WCFWCF_12182/clip_image002_2.jpg"><img style="border-width: 0px; display: block; float: none; margin-left: auto; margin-right: auto;" title="clip_image002" alt="clip_image002" src="http://images.cnblogs.com/cnblogs_com/artech/WindowsLiveWriter/WCFWCF_12182/clip_image002_thumb.jpg" width="598" border="0" height="242" /></a></p>  <p>本例仅仅是为如何通过AOP进行WCF服务调用提供一种思路，并不是一个完备的解决方法（比如，没有考虑安全认证和客户端凭证的设置；没有考虑到双向通信和回调等），有兴趣的读者可以在此继承上进一步地完善。现在，就一步步地进行演示。</p>  <h1><font size="4"><strong>步骤一：创建ChannalFactory&lt;T&gt;的静态工厂：ChannelFactoryCreator</strong></font></h1>  <p>由于服务调用通过服务代理完成，而ChannelFactory&lt;T&gt;是服务代理的创建者，所以在这里先定义一个ChannelFactoryCreator的静态工厂类，通过它来创建或获取ChannelFactory&lt;T&gt;方法。由于ChannelFactory&lt;T&gt;的创建是一件费时的工作，为了提供更好的性能，和ClientBase&lt;T&gt;一样采用了ChannelFactory&lt;T&gt;的缓存机制（《<a target="_blank" href="http://www.cnblogs.com/artech/archive/2009/07/03/1516573.html">ClientBase&lt;T&gt;中对ChannelFactory&lt;T&gt;的缓存机制</a>》）。不过，这里的缓存机制比ClientBase&lt;T&gt;的实现要简单得多，ClientBase&lt;T&gt;通过终结点配置名称、终结点地址和回调对象三者进行缓存，这里仅仅是通过终结点配置名称进行ChannelFactory&lt;T&gt;的缓存，因为我们假设客户端完全使用配置的终结点进行服务调用（这也是我们推荐的使用方式）。下面是整个ChannelFactory&lt;T&gt;的静态工厂类的定义：</p>  <div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">   <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">     <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">using</span> System.Collections;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> <span style="color: #0000ff;">using</span> System.ServiceModel;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span> <span style="color: #0000ff;">namespace</span> Artech.ServiceProxyFactory</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">internal</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span> ChannelFactoryCreator</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> Hashtable channelFactories = <span style="color: #0000ff;">new</span> Hashtable();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> ChannelFactory&lt;T&gt; Create&lt;T&gt;(<span style="color: #0000ff;">string</span> endpointName)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">string</span>.IsNullOrEmpty(endpointName))</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>                 <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ArgumentNullException(<span style="color: #006080;">"endpointName"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>             ChannelFactory&lt;T&gt; channelFactory = <span style="color: #0000ff;">null</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>             <span style="color: #0000ff;">if</span>(channelFactories.ContainsKey(endpointName))</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>                 channelFactory = channelFactories[endpointName] <span style="color: #0000ff;">as</span> ChannelFactory&lt;T&gt;;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>             <span style="color: #0000ff;">if</span> (channelFactory == <span style="color: #0000ff;">null</span>)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum26">  26:</span>                 channelFactory = <span style="color: #0000ff;">new</span> ChannelFactory&lt;T&gt;(endpointName);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum27">  27:</span>                 <span style="color: #0000ff;">lock</span> (channelFactories.SyncRoot)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum28">  28:</span>                 {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum29">  29:</span>                     channelFactories[endpointName] = channelFactory;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum30">  30:</span>                 }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum31">  31:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum32">  32:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum33">  33:</span>             <span style="color: #0000ff;">return</span> channelFactory;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum34">  34:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum35">  35:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum36">  36:</span> }</pre>
<!--CRLF--></div>
</div>

<p>ChannelFactoryCreator中通过一个Hashtable类型的静态变量保存所有创建出来<a href="http://msdn.microsoft.com/en-us/library/ms576132.aspx" target="_blank">ChannelFactory&lt;T&gt;</a>集合，Hashtable的Key为表示终结点配置名称的字符串。在Create&lt;T&gt;方法中，先通过传入的终结点配置名称查看缓存中是否存在已经创建好的<a href="http://msdn.microsoft.com/en-us/library/ms576132.aspx" target="_blank">ChannelFactory&lt;T&gt;</a>对象，如果存在则直接返回，否则创建新的<a href="http://msdn.microsoft.com/en-us/library/ms576132.aspx" target="_blank">ChannelFactory&lt;T&gt;</a>对象,并在返回之前将其加入缓存。</p>

<h1><font size="4"><strong>步骤二：创建自定义RealProxy：ServiceRealProxy&lt;T&gt;</strong></font></h1>

<p>ServiceRealProxy&lt;T&gt;实现了真正的服务调用、异常处理和对服务代理的关闭或中断。ServiceRealProxy&lt;T&gt;的构造函数参数endpointName表示用于服务调用而采用的终结点配置名称。在Invoke中，先借助于ChannelFactoryCreator获得的ChannelFactory&lt;T&gt;创建服务代理对象。然后通过解析参数msg（表示对方法的调用）获得方法调用的参数，并在try控制块中通过反射，传入参数调用服务代理对象相应的方法，从而实现了对服务的调用。对于正常服务调用的结果，将其封装成<a target="_blank" title="ReturnMessage Class" href="http://msdn2.microsoft.com/ct6t4f46.aspx">ReturnMessage</a>对象，并在返回之前调用Close方法关闭服务代理。</p>

<p>在catch控制块中，对抛出的异常进行处理，由于是通过反射方式实现的方法调用，得到的异常类型基本上都是<a target="_blank" title="TargetInvocationException Class" href="http://msdn2.microsoft.com/3tyb11wz.aspx">TargetInvocationException</a>，真正进行服务调用的异常被作为捕获异常的内部异常（InnerException）。所以，我们会判断内部异常是否为CommunicationException或TimeoutException，来决定是否通过调用Abort方法强行中断服务代理。捕获的异常被封装成ReturnMessage对象返回。</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">using</span> System.Runtime.Remoting.Messaging;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> <span style="color: #0000ff;">using</span> System.Runtime.Remoting.Proxies;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span> <span style="color: #0000ff;">using</span> System.ServiceModel;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> <span style="color: #0000ff;">namespace</span> Artech.ServiceProxyFactory</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> ServiceRealProxy&lt;T&gt;: RealProxy</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span> _endpointName;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>         <span style="color: #0000ff;">public</span> ServiceRealProxy(<span style="color: #0000ff;">string</span> endpointName):<span style="color: #0000ff;">base</span>(<span style="color: #0000ff;">typeof</span>(T))</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>             <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">string</span>.IsNullOrEmpty(endpointName))</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>                 <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ArgumentNullException(<span style="color: #006080;">"endpointName"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>             <span style="color: #0000ff;">this</span>._endpointName = endpointName;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">override</span> IMessage Invoke(IMessage msg)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>             T channel = ChannelFactoryCreator.Create&lt;T&gt;(<span style="color: #0000ff;">this</span>._endpointName).CreateChannel();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>             IMethodCallMessage methodCall = (IMethodCallMessage)msg;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>             IMethodReturnMessage methodReturn = <span style="color: #0000ff;">null</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span>             <span style="color: #0000ff;">object</span>[] copiedArgs = Array.CreateInstance(<span style="color: #0000ff;">typeof</span>(<span style="color: #0000ff;">object</span>), methodCall.Args.Length) <span style="color: #0000ff;">as</span> <span style="color: #0000ff;">object</span>[];</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum26">  26:</span>             methodCall.Args.CopyTo(copiedArgs, 0);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum27">  27:</span>             <span style="color: #0000ff;">try</span></pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum28">  28:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum29">  29:</span>                 <span style="color: #0000ff;">object</span> returnValue = methodCall.MethodBase.Invoke(channel, copiedArgs);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum30">  30:</span>                 methodReturn = <span style="color: #0000ff;">new</span> ReturnMessage(returnValue, copiedArgs, copiedArgs.Length, methodCall.LogicalCallContext, methodCall);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum31">  31:</span>                 (channel <span style="color: #0000ff;">as</span> ICommunicationObject).Close();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum32">  32:</span>             }            </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum33">  33:</span>             <span style="color: #0000ff;">catch</span> (Exception ex)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum34">  34:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum35">  35:</span>                 <span style="color: #0000ff;">if</span> (ex.InnerException <span style="color: #0000ff;">is</span> CommunicationException || ex.InnerException <span style="color: #0000ff;">is</span> TimeoutException)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum36">  36:</span>                 {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum37">  37:</span>                     (channel <span style="color: #0000ff;">as</span> ICommunicationObject).Abort();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum38">  38:</span>                 }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum39">  39:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum40">  40:</span>                 <span style="color: #0000ff;">if</span> (ex.InnerException != <span style="color: #0000ff;">null</span>)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum41">  41:</span>                 {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum42">  42:</span>                     methodReturn = <span style="color: #0000ff;">new</span> ReturnMessage(ex.InnerException, methodCall);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum43">  43:</span>                 }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum44">  44:</span>                 <span style="color: #0000ff;">else</span></pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum45">  45:</span>                 {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum46">  46:</span>                     methodReturn = <span style="color: #0000ff;">new</span> ReturnMessage(ex, methodCall);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum47">  47:</span>                 }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum48">  48:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum49">  49:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum50">  50:</span>             <span style="color: #0000ff;">return</span> methodReturn;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum51">  51:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum52">  52:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum53">  53:</span> }</pre>
<!--CRLF--></div>
</div>

<h1><strong><font size="4">步骤三：创建自定义服务代理工厂：ServiceProxyFactory</font></strong></h1>

<p>在本案例中，对于最终的客户端代码来说，它利用的是上面创建的自定义真实代理的透明代理间接地进行服务调用。而该透明代理就是客户端的服务代理，为了便于编程，在这里我们定义一个服务代理的静态工厂类：ServiceProxyFactory</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">namespace</span> Artech.ServiceProxyFactory</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">class</span> ServiceProxyFactory</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> T Create&lt;T&gt;(<span style="color: #0000ff;">string</span> endpointName)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>             <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">string</span>.IsNullOrEmpty(endpointName))</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>                 <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ArgumentNullException(<span style="color: #006080;">"endpointName"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             <span style="color: #0000ff;">return</span> (T)(<span style="color: #0000ff;">new</span> ServiceRealProxy&lt;T&gt;(endpointName).GetTransparentProxy());</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>         }      </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span> }</pre>
<!--CRLF--></div>
</div>

<h1><strong><font size="4">步骤四：通过ServiceProxyFactory创建服务代理进行服务调用</font></strong></h1>

<p>由于重复繁琐的工作已经在ServiceRealProxy&lt;T&gt;中完成，所以客户端进行服务调用的代码将会变得很简洁。为了验证在每次调用完毕后，是否如我们所愿将信道关闭，我们将ServiceProxyFactory应用到我们熟悉的计算服务的例子（终结点calculatorservice配置的绑定类型为<a target="_blank" title="WSHttpBinding Class" href="http://msdn2.microsoft.com/ms586935.aspx">WSHttpBinding</a>）。</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> ICalculator calculator = ServiceProxyFactory.Create&lt;ICalculator&gt;(<span style="color: #006080;">"calculatorservice"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = 1; i &lt; 2000; i++)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     Console.WriteLine(<span style="color: #006080;">"{3}: x + y = {2} when x = {0} and y = {1}"</span>, 1, 2, calculator.Add(1, 2), i);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> }</pre>
<!--CRLF--></div>
</div>

<p>输出结果：</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">1 ： x + y = 3 when x = 1 and y = 2</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">2 ： x + y = 3 when x = 1 and y = 2</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">......</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">1999： x + y = 3 when x = 1 and y = 2</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">2000： x + y = 3 when x = 1 and y = 2</pre>
<!--CRLF--></div>
</div>

<p>从输出的结果可以看出，2000次服务调用成功完成，由此可以证明每次服务调用结束后，会话信道都被成功关闭。会话信道的自动关闭或中断还带来一个好处，由于每次使用的是新信道，所以即使上一个服务调用出错，也不会影响后续的调用。下面的例子证明了这一点：</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> ICalculator calculator = ServiceProxyFactory.Create&lt;ICalculator&gt;(<span style="color: #006080;">"calculatorservice"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">try</span></pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> { </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     Console.WriteLine(<span style="color: #006080;">"x / y = {2} when x = {0} and y = {1}"</span>,2,0,calculator.Divide(2,0));</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span> <span style="color: #0000ff;">catch</span>(Exception ex)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>     Console.WriteLine(ex.Message);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span> }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span> Console.WriteLine(<span style="color: #006080;">"x + y = {2} when x = {0} and y = {1}"</span>,2,0,calculator.Add(2,0));</pre>
<!--CRLF--></div>
</div>

<p>输出结果：</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">The server was unable to process the request due to an internal error.  For more information about the error, either turn on IncludeExceptionDetailInFaults (either from ServiceBehaviorAttribute or from the &lt;serviceDebug&gt; configuration behavior) on the server in order to send the exception information back to the client, or turn on tracing as per the Microsoft .NET Framework 3.0 SDK documentation and inspect the server trace logs.</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">&nbsp;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">x + y = 2 when x = 2 and y = 0</pre>
<!--CRLF--></div>
</div>

<div id="MySignature">作者：<a href="http://artech.cnblogs.com/" target="_blank">Artech</a> 

  <br />出处：<a href="http://artech.cnblogs.com/" target="_blank">http://artech.cnblogs.com</a> 

  <br />本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </div><img src="http://www.cnblogs.com/artech/aggbug/1642607.html?type=1" width="1" height="1" alt=""/><p>评论: 19　<a href="http://www.cnblogs.com/artech/archive/2010/01/08/1642607.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/01/08/1642607.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>WCF技术剖析之三十：一个很有用的WCF调用编程技巧[上篇]</title><link>http://www.cnblogs.com/artech/archive/2010/01/04/1639149.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Mon, 04 Jan 2010 11:46:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2010/01/04/1639149.html</guid><description><![CDATA[<p>阅读: 1570 评论: 38 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2010-01-04 19:46 <a href="http://www.cnblogs.com/artech/archive/2010/01/04/1639149.html" target="_blank">原文链接</a></p><p>在进行基于会话信道的WCF服务调用中，由于受到并发信道数量的限制，我们需要及时的关闭信道；当遇到某些异常，我们需要强行中止（Abort）信道，相关的原理，可以参考我的文章《<a target="_blank" href="http://www.cnblogs.com/artech/archive/2009/07/04/1516908.html">服务代理不能得到及时关闭会有什么后果?</a>》。在真正的企业级开发中，正如我们一般不会让开发人员手工控制数据库连接的开启和关闭一样，我们一般也不会让开发人员手工去创建、开启、中止和关闭信道，这些工作是框架应该完成的操作。这篇文章，我们就来介绍如果通过一些编程技巧，让开发者能够无视&#8220;信道&#8221;的存在，像调用一个普通对象一样进行服务调用。</p>  <h1><font size="4"><strong>一、正常的服务调用方式</strong></font></h1>  <p>如果通过ChannelFactory&lt;TChannel&gt;创建用于服务调用的代理，下面的代码片段描述了客户端典型的服务调用形式：将服务调用在基于代理对象的using块中，并通过try/catch进一步对服务调用操作进行异常处理。当<a target="_blank" title="TimeoutException Class" href="http://msdn2.microsoft.com/cke1faa2.aspx">TimeoutException</a>或者<a target="_blank" title="CommunicationException Class" href="http://msdn2.microsoft.com/ms405965.aspx">CommunicationException</a>被捕获后，调用Abort方法将信道中止。当程序执行到using的末尾，Dispose方法会进一步调用Close方法对信道进行关闭。</p>  <div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">   <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">     <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #0000ff;">class</span> Program</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">{</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">    <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span>[] args)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">    {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">        <span style="color: #0000ff;">using</span> (ChannelFactory&lt;ICalculator&gt; channelFactory = <span style="color: #0000ff;">new</span> ChannelFactory&lt;ICalculator&gt;(<span style="color: #006080;">"calculatorservice"</span>))</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">        {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">            ICalculator calculator = channelFactory.CreateChannel();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">            <span style="color: #0000ff;">using</span> (calculator <span style="color: #0000ff;">as</span> IDisposable)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">            {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                <span style="color: #0000ff;">try</span></pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                    Console.WriteLine(<span style="color: #006080;">"x + y = {2} when x = {0} and y = {1}"</span>, 1, 2, calculator.Add(1, 2));</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                <span style="color: #0000ff;">catch</span> (TimeoutException)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                    (calculator <span style="color: #0000ff;">as</span> ICommunicationObject).Abort();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                    <span style="color: #0000ff;">throw</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                <span style="color: #0000ff;">catch</span> (CommunicationException)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                    (calculator <span style="color: #0000ff;">as</span> ICommunicationObject).Abort();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                    <span style="color: #0000ff;">throw</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">                }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">            }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">        }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">&nbsp;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">        Console.Read();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">    }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;">}</pre>
<!--CRLF--></div>
</div>

<h1><font size="4"><strong>二、借助通过Delegate实现异常处理和服务代理的关闭</strong></font></h1>

<p>虽然上面的编程方式是正确的服务调用方式，但是在真正的应用中，如果在每处进行服务调用的地方都采用上面的方式，在我看来是不能容忍的。这不但会让你的程序显得臃肿不堪，而且带来非常多重复的代码,此外频繁创建ChannelFactory&lt;TChannel&gt;对性能也会有影响。我们可以通过一些公共个方法实现对重复代码（ChannelFactory&lt;TChannel&gt;的创建，服务调用的创建、中止和关闭，以及异常处理）。为此我创建了如下一个ServiceInvoker类型，通过两个重载的Invoke方法实现对目标服务的调用。</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">using</span> System.Collections.Generic;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> <span style="color: #0000ff;">using</span> System.ServiceModel;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span> <span style="color: #0000ff;">namespace</span> Artech.Lib</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> ServiceInvoker</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, ChannelFactory&gt; channelFactories = <span style="color: #0000ff;">new</span> Dictionary&lt;<span style="color: #0000ff;">string</span>, ChannelFactory&gt;();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">object</span> syncHelper = <span style="color: #0000ff;">new</span> <span style="color: #0000ff;">object</span>();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>         <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> ChannelFactory&lt;TChannel&gt; GetChannelFactory&lt;TChannel&gt;(<span style="color: #0000ff;">string</span> endpointConfigurationName)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>             ChannelFactory&lt;TChannel&gt; channelFactory = <span style="color: #0000ff;">null</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>             <span style="color: #0000ff;">if</span> (channelFactories.ContainsKey(endpointConfigurationName))</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>                 channelFactory = channelFactories[endpointConfigurationName] <span style="color: #0000ff;">as</span> ChannelFactory&lt;TChannel&gt;;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>             <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">null</span> == channelFactory)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>                 channelFactory = <span style="color: #0000ff;">new</span> ChannelFactory&lt;TChannel&gt;(endpointConfigurationName);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>                 <span style="color: #0000ff;">lock</span> (syncHelper)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>                 {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>                     channelFactories[endpointConfigurationName] = channelFactory;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span>                 }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum26">  26:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum27">  27:</span>             <span style="color: #0000ff;">return</span> channelFactory;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum28">  28:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum29">  29:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum30">  30:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Invoke&lt;TChannel&gt;(Action&lt;TChannel&gt; action, TChannel proxy)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum31">  31:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum32">  32:</span>             ICommunicationObject channel = proxy <span style="color: #0000ff;">as</span> ICommunicationObject;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum33">  33:</span>             <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">null</span> == channel)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum34">  34:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum35">  35:</span>                 <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ArgumentException(<span style="color: #006080;">"The proxy is not a valid channel implementing the ICommunicationObject interface"</span>, <span style="color: #006080;">"proxy"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum36">  36:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum37">  37:</span>             <span style="color: #0000ff;">try</span></pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum38">  38:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum39">  39:</span>                 action(proxy);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum40">  40:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum41">  41:</span>             <span style="color: #0000ff;">catch</span> (TimeoutException)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum42">  42:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum43">  43:</span>                 channel.Abort();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum44">  44:</span>                 <span style="color: #0000ff;">throw</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum45">  45:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum46">  46:</span>             <span style="color: #0000ff;">catch</span> (CommunicationException)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum47">  47:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum48">  48:</span>                 channel.Abort();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum49">  49:</span>                 <span style="color: #0000ff;">throw</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum50">  50:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum51">  51:</span>             <span style="color: #0000ff;">finally</span></pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum52">  52:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum53">  53:</span>                 channel.Close();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum54">  54:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum55">  55:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum56">  56:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum57">  57:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> TResult Invoke&lt;TChannel, TResult&gt;(Func&lt;TChannel, TResult&gt; function, TChannel proxy)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum58">  58:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum59">  59:</span>             ICommunicationObject channel = proxy <span style="color: #0000ff;">as</span> ICommunicationObject;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum60">  60:</span>             <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">null</span> == channel)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum61">  61:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum62">  62:</span>                 <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ArgumentException(<span style="color: #006080;">"The proxy is not a valid channel implementing the ICommunicationObject interface"</span>, <span style="color: #006080;">"proxy"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum63">  63:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum64">  64:</span>             <span style="color: #0000ff;">try</span></pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum65">  65:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum66">  66:</span>               <span style="color: #0000ff;">return</span>  function(proxy);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum67">  67:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum68">  68:</span>             <span style="color: #0000ff;">catch</span> (TimeoutException)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum69">  69:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum70">  70:</span>                 channel.Abort();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum71">  71:</span>                 <span style="color: #0000ff;">throw</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum72">  72:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum73">  73:</span>             <span style="color: #0000ff;">catch</span> (CommunicationException)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum74">  74:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum75">  75:</span>                 channel.Abort();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum76">  76:</span>                 <span style="color: #0000ff;">throw</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum77">  77:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum78">  78:</span>             <span style="color: #0000ff;">finally</span></pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum79">  79:</span>             {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum80">  80:</span>                 channel.Close();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum81">  81:</span>             }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum82">  82:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum83">  83:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum84">  84:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Invoke&lt;TChannel&gt;(Action&lt;TChannel&gt; action, <span style="color: #0000ff;">string</span> endpointConfigurationName)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum85">  85:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum86">  86:</span>             Guard.ArgumentNotNullOrEmpty(endpointConfigurationName, <span style="color: #006080;">"endpointConfigurationName"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum87">  87:</span>             Invoke&lt;TChannel&gt;(action, GetChannelFactory&lt;TChannel&gt;(endpointConfigurationName).CreateChannel());</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum88">  88:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum89">  89:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum90">  90:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> TResult Invoke&lt;TChannel, TResult&gt;(Func&lt;TChannel, TResult&gt; function, <span style="color: #0000ff;">string</span> endpointConfigurationName)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum91">  91:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum92">  92:</span>             Guard.ArgumentNotNullOrEmpty(endpointConfigurationName, <span style="color: #006080;">"endpointConfigurationName"</span>);           </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum93">  93:</span>             <span style="color: #0000ff;">return</span> Invoke&lt;TChannel, TResult&gt;(function, GetChannelFactory&lt;TChannel&gt;(endpointConfigurationName).CreateChannel());</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum94">  94:</span>         }        </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum95">  95:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum96">  96:</span> }</pre>
<!--CRLF--></div>
</div>

<p>&nbsp;</p>

<p>处于对性能的考虑，避免对ChannelFactory&lt;TChannel&gt;的频繁创建，通过一个字典对象将创建出来的ChannelFactory&lt;TChannel&gt;缓存起来；两个Invoke方法中，服务的调用通过两个Delegate对象（Action&lt;TChannel&gt;和Func&lt;TChannel, TResult&gt;）表示，另一个参数表示终结点的配置名称。那么这时的服务调用就会变得相当简单：</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">using</span> Artech.Lib;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> <span style="color: #0000ff;">using</span> Artech.WcfServices.Contracts;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span> <span style="color: #0000ff;">namespace</span> Artech.WcfServices.Clients</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">class</span> Program</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span>[] args)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>             <span style="color: #0000ff;">int</span> result = ServiceInvoker.Invoke&lt;ICalculator, <span style="color: #0000ff;">int</span>&gt;(calculator =&gt; calculator.Add(1, 2), <span style="color: #006080;">"calculatorservice"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>             Console.WriteLine(<span style="color: #006080;">"x + y = {2} when x = {0} and y = {1}"</span>, 1, 2, result);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             Console.Read();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span> }</pre>
<!--CRLF--></div>
</div>

<h1><font size="4"><strong>三、对ServiceInvoker的改进</strong></font></h1>

<p>实际上，为了对服务调用实现细节进行进一步的封装，一般地我们可以将其定义在一个独立的层中，比如<strong>服务代理层</strong>（这里的层不一定像数据访问层、业务逻辑层一样需要一个明显的界限，这里可能就是一个单独的类型而已）。在这种情况下，我们可以上面的ServiceInvoker方法进行一定的改造，使之更加符合这种分层的场景。上面我们调用静态方法的形式进行服务的调用，现在我们需要的是：实例化服务代理对象，并调用相应的方法。为此，我创建了一个泛型的ServiceInvoker&lt;TChannel&gt;类型，该类型继承自上述的ServiceInvoker，泛型类型表示服务契约类型。ServiceInvoker&lt;TChannel&gt;定义如下：</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">namespace</span> Artech.Lib</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> ServiceInvoker&lt;TChannel&gt;:ServiceInvoker</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> EndpointConfigurationName</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         {get; <span style="color: #0000ff;">private</span> set;}</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         <span style="color: #0000ff;">public</span> ServiceInvoker(<span style="color: #0000ff;">string</span> endpointConfigurationName)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>             Guard.ArgumentNotNullOrEmpty(endpointConfigurationName, <span style="color: #006080;">"endpointConfigurationName"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             <span style="color: #0000ff;">this</span>.EndpointConfigurationName = endpointConfigurationName;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> Invoke(Action&lt;TChannel&gt; action)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>             Invoke&lt;TChannel&gt;(action, <span style="color: #0000ff;">this</span>.EndpointConfigurationName);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>         <span style="color: #0000ff;">public</span> TResult Invoke&lt;TResult&gt;(Func&lt;TChannel, TResult&gt; function)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>             <span style="color: #0000ff;">return</span> Invoke&lt;TChannel, TResult&gt;(function, <span style="color: #0000ff;">this</span>.EndpointConfigurationName);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum24">  24:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum25">  25:</span> }</pre>
<!--CRLF--></div>
</div>

<p>通过传入终结点配置名称创建ServiceInvoker&lt;TChannel&gt;对象，直接通过调用基类的静态方法实现了两个Invoke方法。</p>

<p>在分层设计中，为每一个层定义的组件创建基类是一个很常见的设计方式。在这里，假设所有的服务代理类型均继承自基类：ServiceProxyBase&lt;TChannel&gt;，泛型类型为服务契约类型。同样通过传入终结点配置名称创建服务代理，并借助于通过Invoker属性表示的ServiceInvoker&lt;TChannel&gt;对象进行服务的调用。ServiceProxyBase&lt;TChannel&gt;定义如下：</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">namespace</span> Artech.Lib</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> ServiceProxyBase&lt;TChannel&gt;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> ServiceInvoker&lt;TChannel&gt; Invoker</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>         { get; <span style="color: #0000ff;">private</span> set; }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         <span style="color: #0000ff;">public</span> ServiceProxyBase(<span style="color: #0000ff;">string</span> endpointConfigurationName)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>             Guard.ArgumentNotNullOrEmpty(endpointConfigurationName, <span style="color: #006080;">"endpointConfigurationName"</span>);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>             <span style="color: #0000ff;">this</span>.Invoker = <span style="color: #0000ff;">new</span> ServiceInvoker&lt;TChannel&gt;(endpointConfigurationName);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span> }</pre>
<!--CRLF--></div>
</div>

<p>那么，具体的服务代理类型就可以通过如下的方式定义了：</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> Artech.Lib;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">using</span> Artech.WcfServices.Contracts;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> <span style="color: #0000ff;">namespace</span> Artech.WcfServices.Clients</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> CalculatorProxy : ServiceProxyBase&lt;ICalculator&gt;, ICalculator</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>         <span style="color: #0000ff;">public</span> CalculatorProxy():<span style="color: #0000ff;">base</span>(Constants.EndpointConfigurationNames.CalculatorService)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         { }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span> Add(<span style="color: #0000ff;">int</span> x, <span style="color: #0000ff;">int</span> y)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span>.Invoker.Invoke&lt;<span style="color: #0000ff;">int</span>&gt;(calculator =&gt; calculator.Add(x, y));</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>&nbsp; </pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span>     <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> Constants</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum17">  17:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum18">  18:</span>         <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> EndpointConfigurationNames</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum19">  19:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum20">  20:</span>             <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">const</span> <span style="color: #0000ff;">string</span> CalculatorService = <span style="color: #006080;">"calculatorservice"</span>;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum21">  21:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum22">  22:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum23">  23:</span> }</pre>
<!--CRLF--></div>
</div>

<p>那么现在服务代理的消费者（一般是Presenter层对象），就可以直接实例化服务代理对象，并调用相应的方法（这里的方法与服务契约方法一致）即可，所有关于服务调用的细节均被封装在服务代理中。</p>

<div style="border: 1px solid silver; margin: 20px 0px 10px; padding: 4px; overflow: auto; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 97.5%; font-family: 'Courier New',courier,monospace; direction: ltr; max-height: 200px; font-size: 8pt; cursor: text;" id="codeSnippetWrapper">
  <div style="border-style: none; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;" id="codeSnippet">
    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum1">   1:</span> <span style="color: #0000ff;">using</span> System;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum2">   2:</span> <span style="color: #0000ff;">using</span> Artech.Lib;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum3">   3:</span> <span style="color: #0000ff;">using</span> Artech.WcfServices.Contracts;</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum4">   4:</span> <span style="color: #0000ff;">namespace</span> Artech.WcfServices.Clients</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum5">   5:</span> {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum6">   6:</span>     <span style="color: #0000ff;">class</span> Program</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum7">   7:</span>     {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum8">   8:</span>         <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span>[] args)</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum9">   9:</span>         {</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum10">  10:</span>             CalculatorProxy calculatorProxy = <span style="color: #0000ff;">new</span> CalculatorProxy();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum11">  11:</span>             <span style="color: #0000ff;">int</span> result = calculatorProxy.Add(1, 2);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum12">  12:</span>             Console.WriteLine(<span style="color: #006080;">"x + y = {2} when x = {0} and y = {1}"</span>, 1, 2, result);</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum13">  13:</span>             Console.Read();</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum14">  14:</span>         }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: white; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum15">  15:</span>     }</pre>
<!--CRLF-->

    <pre style="border-style: none; margin: 0em; padding: 0px; overflow: visible; text-align: left; line-height: 12pt; background-color: #f4f4f4; width: 100%; font-family: 'Courier New',courier,monospace; direction: ltr; color: black; font-size: 8pt;"><span style="color: #606060;" id="lnum16">  16:</span> }</pre>
<!--CRLF--></div>
</div>

<p><font size="4"><strong>四、局限</strong></font></p>

<p>这个解决方案有一个很大的局限：服务方式不能包含ref和out参数，因为这两种类型的参数不能作为匿名方法的参数。</p>

<div id="MySignature">作者：<a href="http://artech.cnblogs.com/" target="_blank">Artech</a> 

  <br />出处：<a href="http://artech.cnblogs.com/" target="_blank">http://artech.cnblogs.com</a> 

  <br />本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。 </div><img src="http://www.cnblogs.com/artech/aggbug/1639149.html?type=1" width="1" height="1" alt=""/><p>评论: 38　<a href="http://www.cnblogs.com/artech/archive/2010/01/04/1639149.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2010/01/04/1639149.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item><item><title>入围51CTO 2009年度“最受读者欢迎的IT图书作者”评选</title><link>http://www.cnblogs.com/artech/archive/2009/12/30/1636264.html</link><dc:creator>Artech</dc:creator><author>Artech</author><pubDate>Wed, 30 Dec 2009 10:10:00 GMT</pubDate><guid>http://www.cnblogs.com/artech/archive/2009/12/30/1636264.html</guid><description><![CDATA[<p>阅读: 813 评论: 10 作者: <a href="http://www.cnblogs.com/artech/" target="_blank">Artech</a> 发表于 2009-12-30 18:10 <a href="http://www.cnblogs.com/artech/archive/2009/12/30/1636264.html" target="_blank">原文链接</a></p><p><a href="https://webmail.ncsi.com.cn/exchweb/bin/redir.asp?URL=http://www.china-pub.com/46907%26ref=ps" target="_blank">《WCF技术剖析（卷1）》</a>自出版以来，深受广大WCF爱好者的厚爱，并入围了<a href="https://webmail.ncsi.com.cn/exchweb/bin/redir.asp?URL=http://www.51cto.com/" target="_blank">51CTO</a> 2009年度&#8220;<strong>最受读者欢迎的</strong><strong>IT</strong><strong>图书作者&#8221;</strong>评选，如果你觉得觉得这本书对你学习和使用WCF还有点帮助，你不妨投上一票（同时入围的还有园子里的一哥<a href="http://www.cnblogs.com/Terrylee/" target="_blank">李会军</a>同志）。</p>
<p><strong>投票地址</strong>：<a href="http://book.51cto.com/exp/bookrating2009/author.php" target="_blank">http://book.51cto.com/exp/bookrating2009/author.php</a></p>
<p><strong>姓名：</strong>蒋金楠</p>
<p><strong>投票时间：</strong>2009年12月29日&#8212;2010年1月28日</p>
<p><strong>投票方式</strong>：欢迎您，匿名</p>
<ul><li>匿名投票：此方式将不能参与抽奖。</li><li>ID投票：注册为51CTO会员参与投票，将有机会获得每周的随机抽奖和颁奖现场的超级大奖。 </li></ul>
<p><strong>投票规则：</strong>&#8220;作译者投票&#8221;限每位读者每天累积投票五票。</p><img src="http://www.cnblogs.com/artech/aggbug/1636264.html?type=1" width="1" height="1" alt=""/><p>评论: 10　<a href="http://www.cnblogs.com/artech/archive/2009/12/30/1636264.html#pagedcomment" target="_blank">查看评论</a>　<a href="http://www.cnblogs.com/artech/archive/2009/12/30/1636264.html#commentform" target="_blank">发表评论</a></p><hr/><p>最新新闻：<br/>· <a href="http://news.cnblogs.com/n/56808/" target="_blank">1月必应搜索市场份额破10% 一年内可赶上雅虎</a><span style="color:gray">(2010-02-10 10:42)</span><br/>· <a href="http://news.cnblogs.com/n/56807/" target="_blank">周鸿祎：马化腾的成功在于打动人心</a><span style="color:gray">(2010-02-10 10:39)</span><br/>· <a href="http://news.cnblogs.com/n/56806/" target="_blank">充分保护用户隐私：Adobe Flash Player 10.1beta版本中已加入私密浏览模式</a><span style="color:gray">(2010-02-10 10:34)</span><br/>· <a href="http://news.cnblogs.com/n/56805/" target="_blank">Google 将 Street View 设备放到雪橇上让你看遍冬奥会的雪景</a><span style="color:gray">(2010-02-10 10:29)</span><br/>· <a href="http://news.cnblogs.com/n/56804/" target="_blank">微软追回23个域名所有权</a><span style="color:gray">(2010-02-10 10:22)</span><br/></p><p>编辑推荐：<a href="http://news.cnblogs.com/n/56782/" target="_blank">2010年2月编程语言排行榜</a><br/></p><p>网站导航：<a href="http://www.cnblogs.com" target="_blank">博客园首页</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/" target="_blank">个人主页</a>&nbsp;&nbsp;<a href="http://news.cnblogs.com" target="_blank">新闻</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/ing/" target="_blank">闪存</a>&nbsp;&nbsp;<a href="http://home.cnblogs.com/group/" target="_blank">小组</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com/q/" target="_blank">博问</a>&nbsp;&nbsp;<a href="http://space.cnblogs.com" target="_blank">社区</a>&nbsp;&nbsp;<a href="http://kb.cnblogs.com" target="_blank">知识库</a></p>]]></description></item></channel></rss>