WCF学习 第三天 事务的使用
WCF学习 第三天 事务的使用
今天是速成的第三天,再分享一下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="Data Source=VONXCEVF0IT7JDJ;Initial Catalog=Commerce;Integrated Security=True;MultipleActiveResultSets=True" " 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
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息