wcf系列学习5天速成——第三天 事务的使用
2015-01-16 09:01
435 查看
原文:wcf系列学习5天速成——第三天 事务的使用今天是速成的第三天,再分享一下WCF中比较常用的一种技术,也就是”事务“。
在B2B的项目中,一般用户注册后,就有一个属于自己的店铺,此时,我们就要插入两张表, User和Shop表。
当然,要么插入成功,要么全失败。
第一步: 首先看一下项目的结构图:
第二步: 准备工作,我们新建Commerce数据库,用EF去映射,然后新建ServiceWCF类库,具体步骤就省略,
这一块不懂可以留言。
第三步:新建一个Model类库。建立两个实体类Shop和User,当然自定义类型在WCF中传输,
必须在类上加上【DataContract】,属性上加【DataMember】。
Shop.cs
User.cs
第四步:然后在ServiceWCF类库中新建两个文件Seller.cs 和 ISeller.cs.
ISeller.cs:
Seller.cs
TransactionScopeRequired: 告诉ServiceHost自托管服务,进入我的方法,必须给我加上事务。
TransactionAutoComplete: 方法执行中,如果没有抛出异常,则自动提交。
第五步: 新建Host来承载了,配置AppConfig,这些细节就不再说了。
第六步:开启WCF服务,新建ServiceClient类库,然后用信道生成实例。
最后就是测试了:
首先:走正常流程。client.Add方法调用服务器端,运行效果如图所示:
是的,数据已经正常插入成功,对Client端而言,这个操作是透明的。
然后: 我们在Seller类中的Add方法中故意加入异常。看效果咋样。
截图如下:
哈哈,抛出异常了,我的Exception起到效果了,再来看一下数据库。大家都知道会发生什么了,对的,异常不再产生数据了,
还是先前产生了那条数据,说明起到效果了。
在B2B的项目中,一般用户注册后,就有一个属于自己的店铺,此时,我们就要插入两张表, User和Shop表。
当然,要么插入成功,要么全失败。
第一步: 首先看一下项目的结构图:
第二步: 准备工作,我们新建Commerce数据库,用EF去映射,然后新建ServiceWCF类库,具体步骤就省略,
这一块不懂可以留言。
第三步:新建一个Model类库。建立两个实体类Shop和User,当然自定义类型在WCF中传输,
必须在类上加上【DataContract】,属性上加【DataMember】。
Shop.cs
namespace Model { [DataContract] public class Shop { [DataMember] public int ShopID { get; set; } [DataMember] public int UserID { get; set; } [DataMember] public string ShopName { get; set; } [DataMember] public string ShopUrl { get; set; } } }
User.cs
namespace Model { [DataContract] public class User { [DataMember] public int UserID { get; set; } [DataMember] public string UserName { get; set; } [DataMember] public string Password { get; set; } } }
第四步:然后在ServiceWCF类库中新建两个文件Seller.cs 和 ISeller.cs.
ISeller.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; namespace ServiceWCF { [ServiceContract] public interface ISeller { [OperationContract(Name = "AddUser")] bool Add(Model.User user, out int userID); [OperationContract(Name = "AddShop")] bool Add(Model.Shop shop, out int shopID); [OperationContract] bool Add(Model.User user, Model.Shop shop); } }
Seller.cs
namespace ServiceWCF { public class Seller : ISeller { ///<summary> /// User的插入操作 ///</summary> ///<param name="user"></param> ///<param name="userID"></param> ///<returns></returns> public bool Add(Model.User user, out int userID) { using (CommerceEntities db = new CommerceEntities()) { try { User userModel = new User() { UserName = user.UserName, Passwrod = user.Password }; db.User.AddObject(userModel); db.SaveChanges(); userID = userModel.UserID; return true; } catch (Exception) { userID = 0; throw; } } } ///<summary> /// Shop的插入操作 ///</summary> ///<param name="shop"></param> ///<param name="shopID"></param> ///<returns></returns> public bool Add(Model.Shop shop, out int shopID) { using (CommerceEntities db = new CommerceEntities()) { try { Shop shopModel = new Shop() { ShopName = shop.ShopName, ShopUrl = shop.ShopUrl, UserID = shop.UserID }; db.Shop.AddObject(shopModel); db.SaveChanges(); shopID = shopModel.ShopID; return true; } catch (Exception) { shopID = 0; throw; } } } ///<summary> /// User,Shop的插入的操作 ///</summary> ///<param name="user"></param> ///<param name="shop"></param> ///<returns></returns>
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] public bool Add(Model.User user, Model.Shop shop) { int shopID; int UserID; //注意,这个方法操作了两个数据库实例,为AddUser和AddShop。所以晋升为分布式事务 if (Add(user, out UserID)) { shop.UserID = UserID; return Add(shop, out shopID); } return false; } } }
TransactionScopeRequired: 告诉ServiceHost自托管服务,进入我的方法,必须给我加上事务。
TransactionAutoComplete: 方法执行中,如果没有抛出异常,则自动提交。
第五步: 新建Host来承载了,配置AppConfig,这些细节就不再说了。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ServiceHost { class Program { static void Main(string[] args) { System.ServiceModel.ServiceHost host = new System.ServiceModel.ServiceHost(typeof(ServiceWCF.Seller)); host.Open(); Console.WriteLine("WCF 服务已经开启!"); Console.Read(); } } }
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <compilation debug="true" /> </system.web> <!-- 部署服务库项目时,必须将配置文件的内容添加到 主机的 app.config 文件中。System.Configuration 不支持库的配置文件。--> <system.serviceModel> <services> <service name="ServiceWCF.Seller"> <endpoint address="" binding="wsHttpBinding" contract="ServiceWCF.ISeller"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:8732/Seller/" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior> <!-- 为避免泄漏元数据信息, 请在部署前将以下值设置为 false 并删除上面的元数据终结点 --> <serviceMetadata httpGetEnabled="True" /> <!-- 要接收故障异常详细信息以进行调试, 请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息--> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> <connectionStrings> <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" /> </connectionStrings> </configuration>
第六步:开启WCF服务,新建ServiceClient类库,然后用信道生成实例。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel; using ServiceWCF; namespace ServiceClient { class Program { static void Main(string[] args) { var user = new Model.User() { UserName = "huangxincheng520", Password = "i can fly" }; var shop = new Model.Shop() { ShopName = "shopex", ShopUrl = "http://www.shopex.cn" }; var factory = new ChannelFactory<ISeller>(new WSHttpBinding(),
new EndpointAddress("http://localhost:8732/Seller/")); var client = factory.CreateChannel(); if (client.Add(user, shop)) Console.WriteLine("huangxincheng520, 恭喜你,数据插入成功。"); else Console.WriteLine("huangxincheng520, 呜呜,数据插入失败。"); Console.Read(); } } }
最后就是测试了:
首先:走正常流程。client.Add方法调用服务器端,运行效果如图所示:
是的,数据已经正常插入成功,对Client端而言,这个操作是透明的。
然后: 我们在Seller类中的Add方法中故意加入异常。看效果咋样。
///<summary> /// User,Shop的插入的操作 ///</summary> ///<param name="user"></param> ///<param name="shop"></param> ///<returns></returns> [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] public bool Add(Model.User user, Model.Shop shop) { int shopID; int UserID; if (Add(user, out UserID)) { //注意注意,我在Adduser成功的情况下,抛出异常,看是否回滚。 throw new Exception(); shop.UserID = UserID; return Add(shop, out shopID); } return false; }
截图如下:
哈哈,抛出异常了,我的Exception起到效果了,再来看一下数据库。大家都知道会发生什么了,对的,异常不再产生数据了,
还是先前产生了那条数据,说明起到效果了。
相关文章推荐
- wcf系列学习5天速成——第三天 事务的使用
- wcf系列学习5天速成——第三天 事务的使用
- wcf系列学习5天速成——第三天 事务的使用
- wcf系列学习5天速成——第三天 事务的使用
- wcf系列学习5天速成——第三天 事务的使用
- wcf系列学习5天速成——第三天 事务的使用
- wcf系列学习5天速成——第三天 分布性事务的使用 有时间再验证下 不同库的操作
- wcf系列学习5天速成——第三天 事务的使用(转载)
- wcf系列学习5天速成——第三天 事务的使用
- wcf系列学习5天速成——事务的使用
- wcf系列学习5天速成——第四天 wcf之分布式架构
- wcf系列5天速成——第二天 binding的使用(2)
- wcf系列5天速成——第二天 binding的使用(2)
- WCF学习 第三天 事务的使用
- WCF系列学习5天速成
- wcf系列学习5天速成——第四天 wcf之分布式架构
- wcf系列学习5天速成——第五天 服务托管
- wcf系列学习5天速成——第四天 wcf之分布式架构
- wcf系列5天速成——第二天 binding的使用(2)(转载)
- wcf系列5天速成——第二天 binding的使用(2)