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


    原文地址: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起到效果了,再来看一下数据库。大家都知道会发生什么了,对的,异常不再产生数据了,

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

  • 相关阅读:
    memcached事故
    总算会用sphinx生成文档了
    python tip
    抓包工具wireshark
    狗日的用户体验
    python tip
    pymmseg
    memcached事故
    windwos序列号
    7z fromat on ubuntu&replace my fujishu electric fan
  • 原文地址:https://www.cnblogs.com/niaowo/p/4728253.html
Copyright © 2020-2023  润新知