zoukankan      html  css  js  c++  java
  • 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起到效果了,再来看一下数据库。大家都知道会发生什么了,对的,异常不再产生数据了,

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

  • 相关阅读:
    out/host/linuxx86/obj/EXECUTABLES/aapt_intermediates/aapt 64 32 操作系统
    linux 查看路由器 电脑主机 端口号 占用
    linux proc进程 pid stat statm status id 目录 解析 内存使用
    linux vim 设置大全详解
    ubuntu subclipse svn no libsvnjavahl1 in java.library.path no svnjavahl1 in java.library.path no s
    win7 安装 ubuntu 双系统 详解 easybcd 工具 不能进入 ubuntu 界面
    Atitit.json xml 序列化循环引用解决方案json
    Atitit.编程语言and 自然语言的比较and 编程语言未来的发展
    Atitit.跨语言  文件夹与文件的io操作集合  草案
    Atitit.atijson 类库的新特性设计与实现 v3 q31
  • 原文地址:https://www.cnblogs.com/zpc870921/p/2643954.html
Copyright © 2011-2022 走看看