今天是速成的第三天,再分享一下WCF中比较常用的一种技术,也就是”事务“。

在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 = ;
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 = ;
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=&quot;Data Source=VONXCEVF0IT7JDJ;Initial Catalog=Commerce;Integrated Security=True;MultipleActiveResultSets=True&quot;" 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天速成——第三天 事务的使用的更多相关文章

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

    原文地址:http://www.cnblogs.com/huangxincheng/archive/2011/11/06/2238273.html 今天是速成的第三天,再分享一下WCF中比较常用的一种 ...

  2. wcf系列学习5天速成——第五天 服务托管

    今天是系列的终结篇,当然要分享一下wcf的托管方面的知识. wcf中托管服务一般有一下四种: Console寄宿:             利于开发调试,但不是生产环境中的最佳实践. winform寄 ...

  3. wcf系列学习5天速成——第四天 wcf之分布式架构

    今天是wcf系列的第四天,也该出手压轴戏了.嗯,现在的大型架构,都是神马的, nginx鸡群,iis鸡群,wcf鸡群,DB鸡群,由一个人作战变成了群殴....... 今天我就分享下wcf鸡群,高性能架 ...

  4. WCF系列学习5天速成

    看到一篇比较好的基础wcf学习博客,分享给大家:http://www.cnblogs.com/huangxincheng/archive/2011/10/23/2221845.html

  5. wcf系列5天速成——第一天 binding的使用(1)

    原文:wcf系列5天速成--第一天 binding的使用(1) 作为WCF速成系列,只介绍些项目开发中常用到的实战知识. 学习wcf,还是对其中的几个术语要了解一下.wcf中有一个ABC的概念,就是 ...

  6. Redis 小白指南(三)- 事务、过期、消息通知、管道和优化内存空间

    Redis 小白指南(三)- 事务.过期.消息通知.管道和优化内存空间 简介 <Redis 小白指南(一)- 简介.安装.GUI 和 C# 驱动介绍> 讲的是 Redis 的介绍,以及如何 ...

  7. Mybatis事务(三)事务工厂

    在前面一篇博客Mybatis事务(一)事务管理方式中我们提到,mybatis及spring提供了三个事务实现类:JdbcTransaction.ManagedTransaction和SpringMan ...

  8. 第七节: EF的三种事务的应用场景和各自注意的问题(SaveChanges、DBContextTransaction、TransactionScope)

    一. 什么是事务 我们通俗的理解事务就是一系列操作要么全部成功.要么全部失败(不可能存在部分成功,部分失败的情况). 举一个事务在我们日常生活中的经典例子:两张银行卡(甲.乙),甲向乙转钱,整个过程需 ...

  9. Spring事务(三)事务增强器

    摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.创建事务 1. 获取事务 2. 处理已经存在的事务 3. 准 ...

随机推荐

  1. hibernate连接时指定编码方式 hibernate中文乱码问题

    <property name="connection.url">jdbc:mysql://localhost:3306/cms?useUnicode=true& ...

  2. hdu4135Co-prime 容斥原理水题

    //问一个区间[a,b]与n互素的数的个数 //利用容斥原理可知 //在[a,b] 区间内对n的素数因子 //ans = 被一个数整除的数的个数 - 被两个数的最小公倍数整除的数的个数 + 被三个数的 ...

  3. android典型监听事件实

    public class MainActivity extends Activity { int counter; Button add, sub; TextView display; @Overri ...

  4. 再议Swift操作符重载

    今天我们来谈一谈Swift中的操作 符重载,这一功能非常实用,但是也相当有风险.正所谓“能力越大责任越大”,这句话用来形容操作符重载最合适不过了.它可以令你的代码更加简洁,也可以让 一个函数调用变得又 ...

  5. 【精度问题】【HDU2899】Strange fuction

    Strange fuction Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. 样式布局分享-基于frozen.js的移动OA

    最近改造了公司移动OA的样式,改善了显示效果和用户体验,其中用到了腾讯的 frozen.js 框架,在此把布局代码分享给大家,希望大家可以用得上,具体效果如下图. Demo 百度网盘 下载地址 Git ...

  7. js实现超过长度的字符截取指定长度(中文字符算2个字符),超出部分以...显示

    //超过长度的字符截取指定长度,超出部分以...显示 function subString(str, len) { var newLength = 0; var newStr = "&quo ...

  8. C# 输入输出 常量变量

          //输出 Console.WriteLine("这是一行文字"); 自动回车的. Console.Write("Hello world");  不带 ...

  9. SurfaceView绘图机制

    一.为什么需要用SurfaceView绘图,不直接继承View绘图 它的特性是:可以在主线程之外的线程中向屏幕绘图上.这样可以避免画图任务繁重的时候造成主线程阻塞,从而提高了程序的反应速度.在游戏开发 ...

  10. IC卡

    本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . IC卡 (Integrated Circuit Card,集成电路卡),也称智能卡(Smart card).智慧卡(Intelligent ...