为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
资讯

今天是速成的第三天,再分享一下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起到效果了,再来看一下数据库。大家都知道会发生什么了,对的,异常不再产生数据了,

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

 

 

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消