原文地址:http://www.cnblogs.com/huangxincheng/archive/2011/11/06/2238273.html

今天是速成的第三天,再分享一下WCF中比较常用的一种技术,也就是”事务“。

在B2B的项目中,一般用户注册后,就有一个属于自己的店铺,此时,我们就要插入两张表, User和Shop表。

当然,要么插入成功,要么全失败。

第一步: 首先看一下项目的结构图:

第二步: 准备工作,我们新建Commerce数据库,用EF去映射,然后新建ServiceWCF类库,具体步骤就省略,

这一块不懂可以留言。

第三步:新建一个Model类库。建立两个实体类Shop和User,当然自定义类型在WCF中传输,

必须在类上加上【DataContract】,属性上加【DataMember】。

Shop.cs

 1 namespace Model
2 {
3 [DataContract]
4 public class Shop
5 {
6 [DataMember]
7 public int ShopID { get; set; }
8
9 [DataMember]
10 public int UserID { get; set; }
11
12 [DataMember]
13 public string ShopName { get; set; }
14
15 [DataMember]
16 public string ShopUrl { get; set; }
17
18 }
19 }

User.cs

 1 namespace Model
2 {
3 [DataContract]
4 public class User
5 {
6 [DataMember]
7 public int UserID { get; set; }
8
9 [DataMember]
10 public string UserName { get; set; }
11
12 [DataMember]
13 public string Password { get; set; }
14 }
15 }

第四步:然后在ServiceWCF类库中新建两个文件Seller.cs 和 ISeller.cs.

ISeller.cs:

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Runtime.Serialization;
5 using System.ServiceModel;
6 using System.Text;
7
8 namespace ServiceWCF
9 {
10 [ServiceContract]
11 public interface ISeller
12 {
13 [OperationContract(Name = "AddUser")]
14 bool Add(Model.User user, out int userID);
15
16 [OperationContract(Name = "AddShop")]
17 bool Add(Model.Shop shop, out int shopID);
18
19 [OperationContract]
20 bool Add(Model.User user, Model.Shop shop);
21 }
22 }

Seller.cs

 1 namespace ServiceWCF
2 {
3 public class Seller : ISeller
4 {
5 ///<summary>
6 /// User的插入操作
7 ///</summary>
8 ///<param name="user"></param>
9 ///<param name="userID"></param>
10 ///<returns></returns>
11 public bool Add(Model.User user, out int userID)
12 {
13 using (CommerceEntities db = new CommerceEntities())
14 {
15 try
16 {
17 User userModel = new User()
18 {
19 UserName = user.UserName,
20 Passwrod = user.Password
21 };
22
23 db.User.AddObject(userModel);
24
25 db.SaveChanges();
26
27 userID = userModel.UserID;
28
29 return true;
30 }
31 catch (Exception)
32 {
33 userID = 0;
34 throw;
35 }
36 }
37 }
38
39 ///<summary>
40 /// Shop的插入操作
41 ///</summary>
42 ///<param name="shop"></param>
43 ///<param name="shopID"></param>
44 ///<returns></returns>
45 public bool Add(Model.Shop shop, out int shopID)
46 {
47 using (CommerceEntities db = new CommerceEntities())
48 {
49 try
50 {
51
52 Shop shopModel = new Shop()
53 {
54 ShopName = shop.ShopName,
55 ShopUrl = shop.ShopUrl,
56 UserID = shop.UserID
57 };
58
59 db.Shop.AddObject(shopModel);
60
61 db.SaveChanges();
62
63 shopID = shopModel.ShopID;
64
65 return true;
66 }
67 catch (Exception)
68 {
69 shopID = 0;
70 throw;
71 }
72 }
73 }
74
75 ///<summary>
76 /// User,Shop的插入的操作
77 ///</summary>
78 ///<param name="user"></param>
79 ///<param name="shop"></param>
80 ///<returns></returns>
81         [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
82 public bool Add(Model.User user, Model.Shop shop)
83 {
84 int shopID;
85 int UserID;
86
87 //注意,这个方法操作了两个数据库实例,为AddUser和AddShop。所以晋升为分布式事务
88 if (Add(user, out UserID))
89 {
90 shop.UserID = UserID;
91
92 return Add(shop, out shopID);
93 }
94
95 return false;
96 }
97 }
98 }

TransactionScopeRequired: 告诉ServiceHost自托管服务,进入我的方法,必须给我加上事务。

TransactionAutoComplete:   方法执行中,如果没有抛出异常,则自动提交。

第五步: 新建Host来承载了,配置AppConfig,这些细节就不再说了。

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace ServiceHost
7 {
8 class Program
9 {
10 static void Main(string[] args)
11 {
12 System.ServiceModel.ServiceHost host = new System.ServiceModel.ServiceHost(typeof(ServiceWCF.Seller));
13
14 host.Open();
15
16 Console.WriteLine("WCF 服务已经开启!");
17
18 Console.Read();
19 }
20 }
21 }
 1 <?xml version="1.0" encoding="utf-8"?>
2 <configuration>
3 <system.web>
4 <compilation debug="true" />
5 </system.web>
6 <!-- 部署服务库项目时,必须将配置文件的内容添加到
7 主机的 app.config 文件中。System.Configuration 不支持库的配置文件。-->
8 <system.serviceModel>
9 <services>
10 <service name="ServiceWCF.Seller">
11 <endpoint address="" binding="wsHttpBinding" contract="ServiceWCF.ISeller">
12 <identity>
13 <dns value="localhost" />
14 </identity>
15 </endpoint>
16 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
17 <host>
18 <baseAddresses>
19 <add baseAddress="http://localhost:8732/Seller/" />
20 </baseAddresses>
21 </host>
22 </service>
23 </services>
24 <behaviors>
25 <serviceBehaviors>
26 <behavior>
27 <!-- 为避免泄漏元数据信息,
28 请在部署前将以下值设置为 false 并删除上面的元数据终结点 -->
29 <serviceMetadata httpGetEnabled="True" />
30 <!-- 要接收故障异常详细信息以进行调试,
31 请将以下值设置为 true。在部署前设置为 false
32 以避免泄漏异常信息-->
33 <serviceDebug includeExceptionDetailInFaults="False" />
34 </behavior>
35 </serviceBehaviors>
36 </behaviors>
37 </system.serviceModel>
38 <connectionStrings>
39 <add name="CommerceEntities" connectionString="metadata=res://*/Commerce.csdl|res://*/Commerce.ssdl|res://*/Commerce.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=VONXCEVF0IT7JDJ;Initial Catalog=Commerce;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />
40 </connectionStrings>
41 </configuration>

第六步:开启WCF服务,新建ServiceClient类库,然后用信道生成实例。

 1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.ServiceModel;
6 using ServiceWCF;
7
8 namespace ServiceClient
9 {
10 class Program
11 {
12 static void Main(string[] args)
13 {
14 var user = new Model.User()
15 {
16 UserName = "huangxincheng520",
17 Password = "i can fly"
18 };
19
20 var shop = new Model.Shop()
21 {
22 ShopName = "shopex",
23 ShopUrl = "http://www.shopex.cn"
24 };
25
26 var factory = new ChannelFactory<ISeller>(new WSHttpBinding(),
                                  new EndpointAddress("http://localhost:8732/Seller/"));
27
28 var client = factory.CreateChannel();
29
30 if (client.Add(user, shop))
31 Console.WriteLine("huangxincheng520, 恭喜你,数据插入成功。");
32 else
33 Console.WriteLine("huangxincheng520, 呜呜,数据插入失败。");
34
35 Console.Read();
36 }
37 }
38 }

最后就是测试了:

首先:走正常流程。client.Add方法调用服务器端,运行效果如图所示:

是的,数据已经正常插入成功,对Client端而言,这个操作是透明的。

然后:  我们在Seller类中的Add方法中故意加入异常。看效果咋样。

 1   ///<summary>
2 /// User,Shop的插入的操作
3 ///</summary>
4 ///<param name="user"></param>
5 ///<param name="shop"></param>
6 ///<returns></returns>
7 [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
8 public bool Add(Model.User user, Model.Shop shop)
9 {
10 int shopID;
11 int UserID;
12
13 if (Add(user, out UserID))
14 {
15 //注意注意,我在Adduser成功的情况下,抛出异常,看是否回滚。
16 throw new Exception();
17
18 shop.UserID = UserID;
19
20 return Add(shop, out shopID);
21 }
22
23 return false;
24 }

截图如下:

哈哈,抛出异常了,我的Exception起到效果了,再来看一下数据库。大家都知道会发生什么了,对的,异常不再产生数据了,

还是先前产生了那条数据,说明起到效果了。

wcf系列学习5天速成——第三天 分布性事务的使用 有时间再验证下 不同库的操作的更多相关文章

  1. wcf系列学习5天速成——第三天 事务的使用

    今天是速成的第三天,再分享一下WCF中比较常用的一种技术,也就是”事务“. 在B2B的项目中,一般用户注册后,就有一个属于自己的店铺,此时,我们就要插入两张表, User和Shop表. 当然,要么插入 ...

  2. wcf系列学习5天速成——第五天 服务托管

    今天是系列的终结篇,当然要分享一下wcf的托管方面的知识. wcf中托管服务一般有一下四种: Console寄宿:             利于开发调试,但不是生产环境中的最佳实践. winform寄 ...

  3. wcf系列学习5天速成——第四天 wcf之分布式架构

    今天是wcf系列的第四天,也该出手压轴戏了.嗯,现在的大型架构,都是神马的, nginx鸡群,iis鸡群,wcf鸡群,DB鸡群,由一个人作战变成了群殴....... 今天我就分享下wcf鸡群,高性能架 ...

  4. WCF系列学习5天速成

    看到一篇比较好的基础wcf学习博客,分享给大家:http://www.cnblogs.com/huangxincheng/archive/2011/10/23/2221845.html

  5. wcf系列5天速成——第一天 binding的使用(1)

    原文:wcf系列5天速成--第一天 binding的使用(1) 作为WCF速成系列,只介绍些项目开发中常用到的实战知识. 学习wcf,还是对其中的几个术语要了解一下.wcf中有一个ABC的概念,就是 ...

  6. javaweb(三十八)——mysql事务和锁InnoDB(扩展)

    MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备就My ...

  7. linux下oracle11G DG搭建(三):环绕备库搭建操作

    linux下oracle11G DG搭建(三):环绕备库搭建操作 环境 名称 主库 备库 主机名 bjsrv shsrv 软件版本号 RedHat Enterprise5.5.Oracle 11g 1 ...

  8. spring 事物(三)—— 声明式事务管理详解

    spring的事务处理分为两种: 1.编程式事务:在程序中控制事务开始,执行和提交:详情请点此跳转: 2.声明式事务:在Spring配置文件中对事务进行配置,无须在程序中写代码:(建议使用) 我对&q ...

  9. 《手把手教你》系列技巧篇(三十八)-java+ selenium自动化测试-日历时间控件-下篇(详解教程)

    1.简介 理想很丰满现实很骨感,在应用selenium实现web自动化时,经常会遇到处理日期控件点击问题,手工很简单,可以一个个点击日期控件选择需要的日期,但自动化执行过程中,完全复制手工这样的操作就 ...

随机推荐

  1. Adding Validation to our Album Forms 添加类属性的一些验证特性

    Adding Validation to our Album Forms We’ll use the following Data Annotation attributes: Required – ...

  2. 让ie6/7/8兼容css3的圆角阴影等特殊效果的方法 PIE1.0.0及placeholder在这些IE下生效的方法

    PIE地址:http://css3pie.com/ 使用方法1: #login,#AnnouncementBox {  border:3px solid #fff;  -webkit-border-r ...

  3. java通过移位转16进制

    public class Main { public static void main(String []args) { Main main = new Main(); System.out.prin ...

  4. sqlserver-事务处理

    事务的概念:简单说就访问并可能更新数据库中各种数据项的一个程序执行单元,一旦开启事务,所有对数据的操作要么全部执行,要么全部都不执行.单条sql语句本身就是一个事务. 事务的属性: 事务是作为单个逻辑 ...

  5. java 全角、半角字符串转换

    转自:http://www.cnblogs.com/modou/articles/2679815.html     加入了空字符串的验证 半角转全角的方法: /** * @Title: ToSBC * ...

  6. js 表达式与运算符 详解(下)

    比较运算符: > .>= .<. <=.  ==. !=. ===. !==. 比较运算符的结果都为布尔值 ==只比较值是否相等    而    ===比较的是值和数据类型都要 ...

  7. bootstrap-datetimepicker配置选项

    依赖 需要bootstrap的下拉菜单组件 (dropdowns.less) 的某些样式,还有bootstrap的sprites (sprites.less and associated images ...

  8. YII 验证功能

    YII 表单的验证可以在module目录下的xxx.php里面定义验证方法,设定需要验证的字段就行 //用户表单验证,在模型里面设置一个方法,具体表单验证规则        public functi ...

  9. C#.NET快速开发框架-企业版V4.0截图打包下载

    C/S系统开发框架-企业版 V4.0 (Enterprise Edition) http://www.csframework.com/cs-framework-4.0.htm 其它图片打包下载: ht ...

  10. 枚举宏(Adopting Modern Objective-C)

    使用NS_ENUM 和 NS_OPTIONS宏定义枚举.Adopting Modern Objective-C 使用NS_ENUM宏定义一组互斥的枚举值: typedef NS_ENUM(NSInte ...