WCF从理论到实践(13):事务投票

通过上文WCF从理论到实践:事务的学习,我们了解了WCF中实现事务的一些基本常识,但WCF中的事务并不止那么简单,上文中我们欠缺了一个最重要的功能:事务投票,所谓事务投票就是一种灵活控制事务提交的方式,在上文中我们设置服务方法的TransactionAutoComplete为true,其实意味着方法在没有异常的情况下自动投赞成票,但有时我们希望当操作中只有某个数据满足具体条件的时候,才能赞同事务提交,这样上文的实现明显就不满足需求了,此时我们可以用OperationContext.Current.SetTransactionComplete();显示的进行投票。注意,WCF的事务必须在全票通过的时候才能得以提交。本文还是结合银行的例子 来演示一下事务投票,并且搭配一个漂亮的WPF客户端,可谓买一送一了,:)。

本文目的

  1. 进一步学习WCF事务
  2. 顺便体验一下WPF

本文适合读者

本文适合WCF中级用户,至少需要了解事务的基本常识和简单实现,初学者可以先阅读WCF从理论到实践:事务

进一步学习WCF事务

本文中,我们要模拟的现实情境如下,搭建一个联盟银行服务自助系统,这个系统提供在各个银行之间进行自由转帐的功能,按照惯例,系统分为四个层次,分别如下:

层次

项目

服务契约

Jillzhang.Wcf.Transactions.Contracts

服务端

Jillzhang.Wcf.Transactions

宿主程序

Jillzhang.Wcf.Transactions.ICBC-用于模拟工商银行

Jillzhang.Wcf.Transactions.CCB-用于模拟建设银行

客户端

Jillzhang.Wcf.BankClient – 包括一个漂亮的WPF窗体

 

服务契约

我们在此处定义一个IBank的服务契约,它包括四个操作契约,分别为:



操作契约

契约说明

[OperationContract(IsTerminating=false)]
[TransactionFlow(TransactionFlowOption.Allowed)]
 decimal Receive(decimal money);

接受其他银行的汇款,增加本行帐户余额

[OperationContract(IsTerminating = false)] [TransactionFlow(TransactionFlowOption.Allowed)]

decimal Send(decimal money);

给其他银行帐户汇款,减少本行帐户余额

[OperationContract(IsTerminating = false)]

decimal GetBalance();

获取帐户余额

[OperationContract(IsTerminating=false)]

decimal SendOnServer(decimal money,string toBank);

通过一个银行接口,完成汇款操作,其中事务是在服务端进行

 

服务端

服务端,由于我本地没有数据库,偷下懒,就用一个静态变量表示帐户余额了。大家在验证事务的效果的时候,应该将这里的数据存储到数据库中。整个服务端的代码为:

服务端

注意,本文的Receive和Send方法的TransactionAutoComplete设置的为false,这样就需要我们在事务包含的每个方法中均显示的进行事务投票,即调用OperationContext.Current.SetTransactionComplete();如果忽略此处,系统会出现如下的异常:

而且如果TransactionAutoComplete为false的时候,必须将InstanceContextMode设置为PerSession,并且服务契约(ServiceContract)也必须设置SessionMode为Required,否则分别 会出现如下异常:

而如果TransactionAutoComplete为True,则要求TransactionScopeRequired必须同时为True,否则会出现异常:

宿主程序

宿主程序非常简单,我们只是将服务寄宿到两个不同的进程中并且指定不同的服务地址便可,唯一值得注意的是因为服务契约需要事务支持,所以Binding的TransactionFlow也必须为True.

他们的代码分别为:

Jillzhang.Wcf.Transactions.ICBC

ICBC


Jillzhang.Wcf.Transactions.CCB

CCB


客户端

一个WPF应用程序,可以调用服务来模拟银行转帐功能,因为本文着重介绍WCF,对此不作详细赘述,以后在一起学WPF系列中会逐步加以学习,本文只给出主要的xaml文件和.cs文件

Window1.xaml

Windows.xaml


Window1.xaml.cs

Windows.xaml.cs

有两种方式可以实现转帐,上面代码中是在客户端实现事务,另外一种你可以将using (TransactionScope tx = new TransactionScope())块注释起来,然后将下面的注释取消,这样就可以在服务端实现事务。

下面就让我们来看下运行效果吧:

ICBC-工商行服务

CCB-建设行服务

我们漂亮的客户端效果为:

其实中国工商银行和中国建设银行的账户余额均为10,如上图所示,选择中国工商银行,然后输入转帐金额4,点击转帐,运行后效果如下:

选择中国建设银行,可以看到余额为14,如图:

 范例项目下载

 /Files/jillzhang/Jillzhang.Wcf.Transactions.rar

总结

WCF为我们提供了一种显示控制事务提交的方式,即事务投票,我们通过OperationContext.Current.SetTransactionComplete();来投赞成票,而只有参与事务的全部方法均投赞成票的时候,事务才能被成功提交。显示的投票方法比声明TransactionAutoComplet为true更灵活。同时我们又体验了一把WPF的魅力。

作者:jillzhang
出处:http://jillzhang.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
标签: WCF
posted @ 2008-04-04 22:22 Robin Zhang 阅读(5027) 评论(13) 编辑 收藏

 回复 引用 查看   
#1楼[楼主] 2008-04-04 22:53 jillzhang      
WCP与WPF两个,一个主内,一个主外,珠联璧合呀,我觉得这两项技术日后肯定大有前途
 回复 引用 查看   
#2楼 2008-04-05 02:37 李涛      
WCP与WPF的思想都很好
 回复 引用 查看   
#3楼 2008-04-05 09:16 高海东      
wcf事务是不错,但是性能很差的
 回复 引用 查看   
#4楼 2008-04-05 09:36 狼Robot      
学习了。
 回复 引用 查看   
#5楼[楼主] 2008-04-05 10:15 jillzhang      
@高海东
事务本身就是一件浪费性能的事情,你说的应该是相对数据库事务的吧?不过性能和健壮性也要平衡考虑的,应该属于设计范畴

 回复 引用 查看   
#6楼[楼主] 2008-04-05 10:16 jillzhang      
@狼Robot
共同学习

 回复 引用 查看   
#7楼 2008-04-09 15:32 fantasy_kli      
在这个程序里面加上WPF之后简直不一样啊
 回复 引用 查看   
#8楼 2008-06-17 10:55 魔方      
楼主,为何我下载你的范例代码后,在我的电脑上运行会出现异常啊?
 回复 引用   
#9楼 2008-11-26 15:13 windy.lei[未注册用户]
分布式事务投票不通过如何回滚呢
 回复 引用 查看   
#10楼 2011-04-08 14:54 xc#      
同问,事务失败后,如何回滚?
 回复 引用 查看   
#11楼 2011-04-20 15:42 websharp      
请问楼主在生成BankProxy是自动生成的么。如果是的话那是在什么时候生成?