Step by Step WCF—Transactions

Step by Step WCF—Transactions

在本次实验中,你将会和一个银行的程序打交道。通过这个程序,你将会看到如何加入transaction。首先你需要创建一个数据库。打开Transactions文件夹,使用Bank.sql脚本创建数据库。

打开Bank.sln解决方案。想往常一样,解决方案中包含了服务端和客户端的程序。我们先来看服务端。服务端包含了AccountService和AccountManger两个服务。AccountService实现了IAccount接口,用于完成借贷功能:

Step by Step WCF—Transactions
[ServiceContract]
Step by Step WCF—Transactions
interface

 IAccount
Step by Step WCF—TransactionsStep by Step WCF—Transactions
Step by Step WCF—Transactions

{

Step by Step WCF—Transactions   [OperationContract]
Step by Step WCF—Transactions 
void Credit(int accountNumber,decimal
 amount);
Step by Step WCF—Transactions
Step by Step WCF—Transactions   [OperationContract]
Step by Step WCF—Transactions   
void Debit(int accountNumber,decimal
 amount);
Step by Step WCF—Transactions}


Step by Step WCF—Transactions[ServiceBehavior(InstanceContextMode 

=
 InstanceContextMode.PerCall)]
Step by Step WCF—Transactions
class

 AccountService : IAccount
Step by Step WCF—TransactionsStep by Step WCF—Transactions
Step by Step WCF—Transactions

{

Step by Step WCF—Transactions   
public void Credit(int accountNumber,decimal
 amount)
Step by Step WCF—TransactionsStep by Step WCF—Transactions 
Step by Step WCF—Transactions
{

Step by Step WCF—Transactions      BankAccountsTableAdapter adapter 
= new
 BankAccountsTableAdapter();
Step by Step WCF—Transactions      BankDataSet.BankAccountsDataTable accounts 
=
 adapter.GetData();
Step by Step WCF—Transactions
Step by Step WCF—Transactions      BankDataSet.BankAccountsRow account 
=
 accounts.FindByNumber(accountNumber);
Step by Step WCF—Transactions      account.Balance 
+=
 amount;
Step by Step WCF—Transactions      adapter.Update(accounts);
Step by Step WCF—Transactions   }

Step by Step WCF—Transactions 
public void Debit(int accountNumber,decimal amount)
Step by Step WCF—TransactionsStep by Step WCF—Transactions 
Step by Step WCF—Transactions
{

Step by Step WCF—Transactions      BankAccountsTableAdapter adapter 
= new
 BankAccountsTableAdapter();
Step by Step WCF—Transactions      BankDataSet.BankAccountsDataTable accounts 
=
 adapter.GetData();
Step by Step WCF—Transactions
Step by Step WCF—Transactions      BankDataSet.BankAccountsRow account 
=
 accounts.FindByNumber(accountNumber);
Step by Step WCF—Transactions
Step by Step WCF—Transactions      
if(account.Balance >=
 amount)
Step by Step WCF—TransactionsStep by Step WCF—Transactions      
Step by Step WCF—Transactions
{

Step by Step WCF—Transactions         account.Balance 
-=
 amount;
Step by Step WCF—Transactions      }

Step by Step WCF—Transactions      
else
Step by Step WCF—TransactionsStep by Step WCF—Transactions      
Step by Step WCF—Transactions{

Step by Step WCF—Transactions         
throw new InvalidOperationException(Debit amount is greater than balance in account # +
 accountNumber);
Step by Step WCF—Transactions      }

Step by Step WCF—Transactions      adapter.Update(accounts);
Step by Step WCF—Transactions   }

Step by Step WCF—Transactions}


Step by Step WCF—Transactions
Step by Step WCF—Transactions

代码不是很复杂,这里就不讲解了。
配置文件对AccountService暴露了两个endpoint,一个使用TCP、一个使用HTTP:

Step by Step WCF—Transactions<service name = “AccountService”>

Step by Step WCF—Transactions

<
endpoint
Step by Step WCF—Transactions   
address  = “net.tcp://localhost:8001/AccountService/”


Step by Step WCF—Transactions   binding  

= “netTcpBinding”

Step by Step WCF—Transactions   contract 

= “IAccount”

Step by Step WCF—Transactions

/>

Step by Step WCF—Transactions

<
endpoint
Step by Step WCF—Transactions   
address  = “http://localhost:8002/AccountService”


Step by Step WCF—Transactions   binding  

= “wsHttpBinding”

Step by Step WCF—Transactions   contract 

= “IAccount”

Step by Step WCF—Transactions

/>

Step by Step WCF—Transactions

</service>

Step by Step WCF—Transactions

AccountManger类实现了IAccountManger接口,用来查询帐户:

Step by Step WCF—Transactions
[DataContract]
Step by Step WCF—Transactions
class

 Account
Step by Step WCF—TransactionsStep by Step WCF—Transactions
Step by Step WCF—Transactions

{

Step by Step WCF—Transactions   [DataMember]
Step by Step WCF—Transactions   
public string
 Name;
Step by Step WCF—Transactions
Step by Step WCF—Transactions   [DataMember]
Step by Step WCF—Transactions   
public decimal
 Balance;
Step by Step WCF—Transactions
Step by Step WCF—Transactions   [DataMember]
Step by Step WCF—Transactions   
public int
 Number;
Step by Step WCF—Transactions}


Step by Step WCF—Transactions
Step by Step WCF—Transactions[ServiceContract]
Step by Step WCF—Transactions

interface
 IAccountManager
Step by Step WCF—TransactionsStep by Step WCF—Transactions
Step by Step WCF—Transactions

{

Step by Step WCF—Transactions   [OperationContract]
Step by Step WCF—Transactions   Account[] GetAccounts();
Step by Step WCF—Transactions}


Step by Step WCF—Transactions

我们再来看客户端。客户端使用了一个winform程序来模拟银行的操作:
 Step by Step WCF—Transactions
点击Transfer按钮将会做转帐的操作。在代码上,client端会对第一个帐户创建一个TCP代理类来完成贷款动作。接下来会对第二个帐户创建一个HTTP代理类来完成借款动作。完成转帐动作后会重新获取帐户信息显示到grid中。

Step by Step WCF—Transactionsusing(AccountClient account1 = new AccountClient(TCP
))
Step by Step WCF—Transactions
using(AccountClient account2 = new AccountClient(HTTP

))
Step by Step WCF—TransactionsStep by Step WCF—Transactions
Step by Step WCF—Transactions

{

Step by Step WCF—Transactions   account1.Credit(destinationAccount,amount);
Step by Step WCF—Transactions   account2.Debit(sourceAccount,amount);
Step by Step WCF—Transactions}


Step by Step WCF—Transactions

目前client端没有任何事务控制,也没有错误处理。程序的架构如下图所示:
 Step by Step WCF—Transactions

在没有事务控制的情况下,如果帐户号码是正确的,那么不会出现任何问题。比如我们将100元从帐户123转到456。但是如果帐户输入错误了,那么就会有问题了。比如我们将100元从帐户777转到456。点击Transfer后我们会收到异常(因为程序没有错误处理),不用管这个错误,刷新grid后我们会发现456帐户上多了100元!
 Step by Step WCF—Transactions
接下来我们就加入事务控制吧。

加入事务
为AccountService加入operation behavior:

Step by Step WCF—Transactionsclass
 AccountService : IAccount
Step by Step WCF—TransactionsStep by Step WCF—Transactions
Step by Step WCF—Transactions

{

Step by Step WCF—Transactions    [OperationBehavior(TransactionScopeRequired 
= true
)]
Step by Step WCF—Transactions    
public void Credit(int accountNumber, decimal
 amount)
Step by Step WCF—TransactionsStep by Step WCF—Transactions    
Step by Step WCF—Transactions{……}

Step by Step WCF—Transactions
Step by Step WCF—Transactions    [OperationBehavior(TransactionScopeRequired 
= true)]
Step by Step WCF—Transactions    
public void Debit(int accountNumber, decimal
 amount)
Step by Step WCF—TransactionsStep by Step WCF—Transactions    
Step by Step WCF—Transactions{……}

Step by Step WCF—Transactions}


Step by Step WCF—Transactions
Step by Step WCF—Transactions

为了让事务能传播到服务端,我们需要在服务端加上TransactionFlow的属性。同样也需要在client端的contract定义上加入相同的属性:

Step by Step WCF—Transactions
[ServiceContract]
Step by Step WCF—Transactions
interface

 IAccount
Step by Step WCF—TransactionsStep by Step WCF—Transactions
Step by Step WCF—Transactions

{

Step by Step WCF—Transactions    [OperationContract]
Step by Step WCF—Transactions    [TransactionFlow(TransactionFlowOption.Allowed)]
Step by Step WCF—Transactions    
void Credit(int accountNumber, decimal
 amount);
Step by Step WCF—Transactions
Step by Step WCF—Transactions    [OperationContract]
Step by Step WCF—Transactions    [TransactionFlow(TransactionFlowOption.Allowed)]
Step by Step WCF—Transactions    
void Debit(int accountNumber, decimal
 amount);
Step by Step WCF—Transactions}


Step by Step WCF—Transactions
Step by Step WCF—Transactions

同时还需要在配置文件中对bingding加入允许事务的属性,服务端:

Step by Step WCF—Transactions<services>

Step by Step WCF—Transactions 

<service name = “AccountService”>

Step by Step WCF—Transactions    

<
endpoint
Step by Step WCF—Transactions       
address  = “net.tcp://localhost:8001/AccountService/”


Step by Step WCF—Transactions       binding  

= “netTcpBinding”

Step by Step WCF—Transactions       contract 

= “IAccount”

Step by Step WCF—Transactions    bindingConfiguration

=”TransactionalTCP”

Step by Step WCF—Transactions    

/>

Step by Step WCF—Transactions    

<
endpoint
Step by Step WCF—Transactions       
address  = “http://localhost:8002/AccountService”


Step by Step WCF—Transactions       binding  

= “wsHttpBinding”

Step by Step WCF—Transactions       contract 

= “IAccount”

Step by Step WCF—Transactions    bindingConfiguration

=”TransactionalHTTP”

Step by Step WCF—Transactions    

/>

Step by Step WCF—Transactions 

</service>

Step by Step WCF—Transactions ……
Step by Step WCF—Transactions

</services>

Step by Step WCF—Transactions

<bindings>

Step by Step WCF—Transactions   

<netTcpBinding>

Step by Step WCF—Transactions    

<binding name=”TransactionalTCP” transactionFlow=”true” />

Step by Step WCF—Transactions   

</netTcpBinding>

Step by Step WCF—Transactions   

<wsHttpBinding>

Step by Step WCF—Transactions    

<binding name=”TransactionalHTTP” transactionFlow=”true” />

Step by Step WCF—Transactions   

</wsHttpBinding>

Step by Step WCF—Transactions

</bindings>

客户端:

Step by Step WCF—Transactions<client>

Step by Step WCF—Transactions 

<endpoint name = “TCP”

Step by Step WCF—Transactions    address  

= “net.tcp://localhost:8001/AccountService/”

Step by Step WCF—Transactions    binding  

= “netTcpBinding”

Step by Step WCF—Transactions    contract 

= “IAccount”

Step by Step WCF—Transactions     bindingConfiguration

=”TransactionalTCP”

Step by Step WCF—Transactions 

/>

Step by Step WCF—Transactions 

<endpoint name = “HTTP”

Step by Step WCF—Transactions    address  

= “http://localhost:8002/AccountService/”

Step by Step WCF—Transactions    binding  

= “wsHttpBinding”

Step by Step WCF—Transactions    contract 

= “IAccount”

Step by Step WCF—Transactions     bindingConfiguration

=”TransactionalHTTP”

Step by Step WCF—Transactions 

/>

Step by Step WCF—Transactions……
Step by Step WCF—Transactions

</client>

Step by Step WCF—Transactions

<bindings>

Step by Step WCF—Transactions 

<netTcpBinding>

Step by Step WCF—Transactions  

<binding name=”TransactionalTCP” transactionFlow=”true” />

Step by Step WCF—Transactions 

</netTcpBinding>

Step by Step WCF—Transactions 

<wsHttpBinding>

Step by Step WCF—Transactions  

<binding name=”TransactionalHTTP” transactionFlow=”true” />

Step by Step WCF—Transactions 

</wsHttpBinding>

Step by Step WCF—Transactions

</bindings>

Step by Step WCF—Transactions

对client项目添加对System.Transactions.dll的引用。打开BankClientForm.cs文件,添加using语句:using System.Transactions。
下面,我们将在client端使用transaction scope将它调用的两个服务包到一个事务中:
 Step by Step WCF—Transactions
使用TrasactionScope来包住两个调用:

Step by Step WCF—Transactionsusing(TransactionScope scope = new
 TransactionScope())
Step by Step WCF—Transactions
using (AccountClient account1 = new AccountClient(TCP

))
Step by Step WCF—Transactions
using (AccountClient account2 = new AccountClient(HTTP

))
Step by Step WCF—TransactionsStep by Step WCF—Transactions
Step by Step WCF—Transactions

{

Step by Step WCF—Transactions    account1.Credit(destinationAccount, amount);
Step by Step WCF—Transactions    account2.Debit(sourceAccount, amount);
Step by Step WCF—Transactions    scope.Complete();
Step by Step WCF—Transactions}

重复我们一开始的实验,你会发现帐户不正确时所有操作都会进行回滚。

 

转载于:https://www.cnblogs.com/yunkunyang/archive/2008/04/11/1148703.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/111032.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 分享一份适合练手的软件测试实战项目[通俗易懂]

    分享一份适合练手的软件测试实战项目[通俗易懂]最近,不少读者托我找一个能实际练手的测试项目。开始,我觉得这是很简单的一件事,但当我付诸行动时,却发现,要找到一个对新手友好的练手项目,着实困难。我翻了不下一百个web网页,包括之前推荐练手的政府网站(普遍会有bug),但依旧没能找到合适的。最后,在我苦苦的搜寻过程中,突然蹦跶出来一条引流广告,我随手点进去,误打误撞,发现了一个适合练手的web网页,因此推荐给还是测试新手的你。项目实战网站:吉屋网模块:房价链接:http://cd.jiwu.com/fangjia/项目简介:一个提供地区房价信

    2022年6月14日
    47
  • 堆叠降噪自动编码器 Stacked Denoising Auto Encoder(SDAE)

    堆叠降噪自动编码器 Stacked Denoising Auto Encoder(SDAE)自动编码器(Auto-Encoder,AE)自编码器(autoencoder)是神经网络的一种,经过训练后能尝试将输入复制到输出。自编码器内部有一个隐藏层h,可以产生编码(code)表示输入。该网络可以看作由两部分组成:一个由函数h=f(x)表示的编码器和一个生成重构的解码器r=g(h)。我们不应该将自编码器设计成输入到输出完全相等。这通常需要向自编码器强加一些约束,使它只能近…

    2022年5月22日
    53
  • c++常用头文件和函数_C加加头文件

    c++常用头文件和函数_C加加头文件文章目录常用头文件下的函数介绍:cstring/string.h1.strlen()2.strcmp()3.strcpy()4.strcat()常用头文件下的函数介绍:cstring/string.hC语言提供了很多实用的数学函数,如果要使用,需要在程序开头添加头文件cstring或者string.h。//二者选一#include<cstring>#include<string.h>1.strlen()strlen(str)用于得到字符数组中第一个\0前

    2025年8月29日
    9
  • 常见的目标检测算法介绍[通俗易懂]

    常见的目标检测算法介绍[通俗易懂]2018-12-0521:12:15一、滑动窗口目标检测首先通过卷积神经网络训练一个分类器,然后使用不同尺度的窗口去裁剪输入图片进行分类。我们期望的结果是通过不同的窗口可以将需要检测的物体完全覆

    2022年8月6日
    6
  • html.dropdownlistfor_see的用法

    html.dropdownlistfor_see的用法常用方法后台代码:publicActionResultIndex(){ViewData[“deptOu”]=”SOHO”;using(ISessionsession=newNHibernateHelper(DataBase.ADDB).OpenSession()){IList<t_data_DeptOU>dep…

    2022年10月10日
    4
  • 思维导图☆三招十八式「建议收藏」

    思维导图☆三招十八式「建议收藏」思维导图三招十八式http://www.795.com.cn/wz/55075.html思维导图三招十八式之一:思维导图进行资料整理学习力的革命系列暂时结束,从今天开始转载三招十八式系列,这个系列都是讲思维导图的各种应用技巧。为了让大家知道具体是什么,我把文字版放在下面,看完后,觉得有用,请下载完全版,后面的附件就是  写在前面的话  关于思维导图软件的使用,一般来说是很简单的,这些软件的使用

    2022年10月21日
    5

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号