数据一致性在工作中显得非常重要,有时候我们库中出现脏数据导致程序报错,但是又很难发现这样的错误,所以为了数据的完整性建议在程序中加入事物。

什么是事物:我们都有团队合作吧,比喻团队有3个人,a负责设计,b负责前端,c负责后台,那么他们三个就是一个整体,哪一个人那里出了问题就要被打回。

第一步:我们开始定义个一个接口

[ServiceContract]
public interface IUserInfo {
[OperationContract]
int AddInfo();
}

第二步当然是实现接口了。这个AddInfo需要添加用户和文章

//使用隐式事务,并把TransactionFlowOption设置为Allowed打开事务流
[OperationBehavior(TransactionAutoComplete = true, TransactionScopeRequired = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]
public int AddInfo()
{
using (TransactionScope transcope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
try
{
if (AddUser())
{
if (!AddArticle())
{
Transaction.Current.Rollback();
return ;
}
else {
transcope.Complete();
return ;
}
}
else {
Transaction.Current.Rollback();
}
}
catch (Exception ep)
{
Transaction.Current.Rollback();
return ;
}
return ;
}
}
/// <summary>
/// 添加用户
/// </summary>
/// <returns></returns>
public bool AddUser() {
try {
string guid = System.Guid.NewGuid().ToString();
string userName = "zhangsan";
string realName = "张三";
DateTime dateTime = DateTime.Now;
string sql = "insert into MyUser(Id,UserName,RealName,SysDate)values(@Id,@UserName,@RealName,@SysDate)";
SqlParameter[] param = new SqlParameter[]
{
new SqlParameter("@Id",guid),
new SqlParameter("@UserName",userName),
new SqlParameter("@RealName",realName),
new SqlParameter("@SysDate",dateTime)
};
string Conn = ConfigurationManager.ConnectionStrings["dbLink"].ConnectionString;
return SqlHelper.ExecuteNonQuery(Conn, CommandType.Text, sql, param) > ;
}
catch (Exception) {
return false;
}
}
/// <summary>
/// 文献信息
/// </summary>
/// <returns></returns>
public bool AddArticle() {
try {
string guid = System.Guid.NewGuid().ToString();
string Title = null;
string Content = "我在测试";
DateTime dateTime = DateTime.Now;
string sql = "insert into Info(Id,Title,Content,SysDate)values(@Id,@Title,@Content,@SysDate)";
SqlParameter[] param = new SqlParameter[]
{
new SqlParameter("@Id",guid),
new SqlParameter("@Title",Title),
new SqlParameter("@Content",Content),
new SqlParameter("@SysDate",dateTime)
};
string Conn = ConfigurationManager.ConnectionStrings["dbLink"].ConnectionString;
return SqlHelper.ExecuteNonQuery(Conn, CommandType.Text, sql, param) > ;
}
catch (Exception ep)
{
return false;
}
}

注释1:TransactionAutoComplete=true的时候表示没有异常的时候自动完成事物范围

第三步:显得方法AddArticle()添加不进去库,我在数据库中不准为null,看下单元测试

public void AddInfoTest()
{
UserInfoClient.UserInfoClient userInfo=new UserInfoClient.UserInfoClient();
int result = userInfo.AddInfo();
Assert.AreEqual(, result);
}

效果:

第四步:说明事物我们实现了,但是很多时候我们都是和别的部门或者调用别人的wcf所以需要如果其中任何一方数据出现错误就要需要回滚现在我们开始写第二个wcf接口

接口同上,现在看下方法

public class User : IUser {
//使用隐式事务,并把TransactionFlowOption设置为Allowed打开事务流
[OperationBehavior(TransactionAutoComplete = true, TransactionScopeRequired = true)]
[TransactionFlow(TransactionFlowOption.Allowed)]
public int AddInfo() {
Client.UserInfoClient userInfoClient = new UserInfoClient();
using (TransactionScope transcope = new TransactionScope(TransactionScopeOption.RequiresNew)) {
try {
if (!AddUser()) {
Transaction.Current.Rollback();
return ;
}
if (!AddArticle()) {
Transaction.Current.Rollback();
return ;
}
if (userInfoClient.AddInfo() != ) {
Transaction.Current.Rollback();
return ;
}
else {
transcope.Complete();
return ;
}
}
catch (Exception) {
Transaction.Current.Rollback();
userInfoClient.Close();
return ;
}
}

其中调用的AddUser()和AddArticle()同上面一样(这里仅仅为了测试)userInfoClient.AddInfo()这是上一个wcf部署以后的方法

现在我们先看都成功都添加成功(此时成功添加数据库)

[Test]
public void AddInfoTwoTest()
{
Client.UserClient userClient =new UserClient();
Assert.AreEqual(, userClient.AddInfo());
}

效果:

再看第一个wcf添加失败第二个回滚的效果

        /// <summary>
/// 测试回滚
/// </summary>
[Test]
public void AddInfoFailTest()
{
Client.UserClient userClient = new UserClient();
Assert.AreEqual(, userClient.AddInfo());
}

总结:在我们一条数据插入多个表中,或者数据之间有很强的联系,我们可以考虑用事物老保证数据一致性,但是一定注意记得事物要提交,否则可能会出席死锁。大家可以动手试试

源码下载

我们一起学习WCF 第十篇Wcf中实现事务的更多相关文章

  1. [老老实实学WCF] 第十篇 消息通信模式(下) 双工

    老老实实学WCF 第十篇 消息通信模式(下) 双工 在前一篇的学习中,我们了解了单向和请求/应答这两种消息通信模式.我们知道可以通过配置操作协定的IsOneWay属性来改变模式.在这一篇中我们来研究双 ...

  2. Dubbo学习系列之十五(Seata分布式事务方案TCC模式)

    上篇的续集. 工具: Idea201902/JDK11/Gradle5.6.2/Mysql8.0.11/Lombok0.27/Postman7.5.0/SpringBoot2.1.9/Nacos1.1 ...

  3. 重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系

    重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系 Innodb中的事务隔离级别和锁的关系 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁 ...

  4. Egret入门学习日记 --- 第二十篇(书中 9.1~9.3 节 内容 组件篇)

    第二十篇(书中 9.1~9.3 节 内容 组件篇) 第八章中的内容. 以上都是基本的Js知识,我就不录入了. 直接来看 第9章. 开始 9.1节. 以上内容告诉你,Egret官方舍弃了GUI,使用了E ...

  5. Egret入门学习日记 --- 第十篇(书中 2.9~2.13节 内容)

    第十篇(书中 2.9~2.13节 内容) 好的 2.9节 开始! 总结一下重点: 1.之前通过 ImageLoader 类加载图片的方式,改成了 RES.getResByUrl 的方式. 跟着做: 重 ...

  6. MyCat 学习笔记 第十篇.数据分片 之 ER分片

    1 应用场景 这篇来说下mycat中自带的er关系分片,所谓er关系分片即可以理解为有关联关系表之间数据分片.类似于订单主表与订单详情表间的分片存储规则. 本文所说的er分片分为两种: a. 依据主键 ...

  7. Python学习【第十篇】基础之杂货铺

    字符串格式化 Python的字符串格式化有两种方式: 百分号方式.format方式 百分号的方式相对来说比较老,而format方式则是比较先进的方式,企图替换古老的方式,目前两者并存. 百分号方式: ...

  8. MySQL学习【第十篇存储引擎实际应用】

    一.将现有的myiasm引擎转化为innodb引擎 1.首先我们知道myisam有几点特别烦 a( 运用的是表级锁 b( 不支持csr(故障自动恢复) 2.mysql的5.1.177版本innodb引 ...

  9. Django学习笔记第十篇--实战练习六--发送邮件

    一.发送邮件需要引入的包依赖文件(Django1.8 Python2.7) from django.core.mail import send_mail,send_mass_mail 其中send_m ...

随机推荐

  1. Linux学习总结(十八)几个简单的文本处理工具cut sort tr split

    1 命令cut 用来截取某一个字段格式 : cut -d '分隔符' [-cf] n, n为数字,表示第几段-d:后面跟分隔符,分割符要加单引号-c:后面接的是第几个字符-f:后面接的是第几段那么意思 ...

  2. Owin+ASP.NET Identity浅析系列(三)框架结构分析

    在今天,读书有时是件“麻烦”事.它需要你付出时间,付出精力,还要付出一份心境.--仅以<Owin+ASP.NET Identity浅析系列>来祭奠那逝去的…… 前两篇博客仅仅说了下功能如何 ...

  3. leetcode64. Minimum Path Sum

    这个题是从左上角到右下角的路径和最小,实际就是一道dp题. 第一种写法是只初始化(0,0)位置,第二种写法则是把第一行.第一列都初始化了.个人更喜欢第二种写法,简单一点. dp的右下角的值就为最终的值 ...

  4. 跳转到系统设置界面 iOS

    NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; if ([[UIApplication sharedApp ...

  5. TabActivity 、fragemnt+fragment 和 Fragment+Viewpager 优缺点

    1 TabActivity : 1 过时了 . 2 activity . 是作为android的四大组件...                   重量级的家伙   ViewGroup   : 特别麻 ...

  6. HDU 1142 A Walk Through the Forest(最短路+记忆化搜索)

    A Walk Through the Forest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Jav ...

  7. sharepoint OOS打开文档使用新窗口

    总体说来就是在<a>标签上嵌入_blank $("a[onclick*='return DispEx'][target!='_blank']") .attr(" ...

  8. React Native封装Toast与加载Loading组件

    React Native开发封装Toast与加载Loading组件 在App开发中,我们避免不了使用的两个组件,一个Toast,一个网络加载Loading,在RN开发中,也是一样,React Nati ...

  9. c++友元函数、友元类、友成员函数

    友元函数:不是类成员函数,是一个类外的函数,但是可以访问类所有成员. class Point{ public: friend void fun(Point t);//友元函数 private: int ...

  10. 用Google Cloud Plateform使用ansible创建新实例

    谷歌大法好,退aws保平安 ---假设自己现在有一个电脑(本机),先用谷歌云创一个服务器(主机) ,再通过ansible在谷歌云上创建一个服务器(节点)并进行控制 先把自己的公钥加到元数据里面,在go ...