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

转载 2012年03月22日 15:34:00

今天是速成的第三天,再分享一下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天速成——第三天 事务的使用

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

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

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

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

wcf系列学习5天速成——第四天 wcf之分布式架构 今天是wcf系列的第四天,也该出手压轴戏了。嗯,现在的大型架构,都是神马的, nginx鸡群,iis鸡群,wcf鸡群,DB鸡群,由一个人作战变成了...
  • mss359681091
  • mss359681091
  • 2016年11月29日 18:01
  • 476

【.Net码农】huangxincheng一线码农系列--wcf系列学习5天速成

wcf系列学习5天速成——第五天 服务托管 摘要: 今天是系列的终结篇,当然要分享一下wcf的托管方面的知识。wcf中托管服务一般有一下四种:Console寄宿: 利于开发调试,但不是生...
  • CrackLibby
  • CrackLibby
  • 2014年11月11日 16:52
  • 498

2016数学建模国赛五天突击笔记

第一天 一.概率论中的方法 参数估计:用于模型的数学形式已知,并且可以用有限个参数表示,利用样本对参数进行估计。 二项分布的参数估计(binofit)、正态分布的参数估计(normfit)、指数...
  • qq_34637672
  • qq_34637672
  • 2016年08月29日 08:12
  • 464

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

作为WCF速成系列,只介绍些项目开发中常用到的实战知识。   学习wcf,还是对其中的几个术语要了解一下。wcf中有一个ABC的概念,就是            第一: "A" 是地址,就是告诉...
  • mss359681091
  • mss359681091
  • 2016年11月29日 17:58
  • 325

wcf系列5天速成——第二天 binding的使用(2)

承接上一章,今天来讲MSMQ在实战项目中的应用。众所周知,放了防止订单丢失,我们都是采用Order过一下MSMQ。     MSMQ的优点个人认为是:先天的异步消息发送和天生的自动负载均衡。   ...
  • mss359681091
  • mss359681091
  • 2016年11月29日 17:59
  • 240

在WCF中实现事务

1. WCF服务中事务的边界 WCF服务中,事务是以方法为边界的,每个WCF服务的方法可以有独立事务的执行模式。而事务可以在多个服务中传播,也可以在服务端与客户端之间传播,介时事务管理器的级数将会晋...
  • wyxhd2008
  • wyxhd2008
  • 2012年09月06日 09:28
  • 4460

WCF系列_分布式事务(上)

1、 事务协议 跟WCF相关的事务协议有三个。 1.1.   Lightweight protocol 这是个轻量级的本地事务协议,限制管理在一个AppDomain中的事务。不能跨AppDoma...
  • xwnxwn
  • xwnxwn
  • 2015年03月07日 09:35
  • 489

WCF系列_分布式事务(下)

1、 WCF分布式事务例子 这里也用转账的例子说事。 用户在系统A和系统B都有账户,账户间的资金可以互转,系统A的资金减少多少,系统B的相应账户的资金就增加多少。 系统A机器上有数据库Accou...
  • xwnxwn
  • xwnxwn
  • 2015年03月07日 09:37
  • 743
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:wcf系列学习5天速成——第三天 事务的使用
举报原因:
原因补充:

(最多只允许输入30个字)