我们一起学习WCF 第十篇Wcf中实现事务
数据一致性在工作中显得非常重要,有时候我们库中出现脏数据导致程序报错,但是又很难发现这样的错误,所以为了数据的完整性建议在程序中加入事物。
什么是事物:我们都有团队合作吧,比喻团队有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 0; } else { transcope.Complete(); return 1; } } else { Transaction.Current.Rollback(); } } catch (Exception ep) { Transaction.Current.Rollback(); return 0; } return 0; } } /// <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) > 0; } 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) > 0; } 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(0, 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 0; } if (!AddArticle()) { Transaction.Current.Rollback(); return 0; } if (userInfoClient.AddInfo() != 1) { Transaction.Current.Rollback(); return 0; } else { transcope.Complete(); return 1; } } catch (Exception) { Transaction.Current.Rollback(); userInfoClient.Close(); return 0; } }
其中调用的AddUser()和AddArticle()同上面一样(这里仅仅为了测试)userInfoClient.AddInfo()这是上一个wcf部署以后的方法
现在我们先看都成功都添加成功(此时成功添加数据库)
[Test] public void AddInfoTwoTest() { Client.UserClient userClient =new UserClient(); Assert.AreEqual(1, userClient.AddInfo()); }
效果:
再看第一个wcf添加失败第二个回滚的效果
/// <summary> /// 测试回滚 /// </summary> [Test] public void AddInfoFailTest() { Client.UserClient userClient = new UserClient(); Assert.AreEqual(0, userClient.AddInfo()); }
总结:在我们一条数据插入多个表中,或者数据之间有很强的联系,我们可以考虑用事物老保证数据一致性,但是一定注意记得事物要提交,否则可能会出席死锁。大家可以动手试试
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?