TransactionScope事务处理方法介绍及.NET Core中的注意事项

作者:依乐祝

原文链接:https://www.cnblogs.com/yilezhu/p/10170712.html

今天在写CzarCms的UnitOfWork的使用使用到了这个TransactionScope事务,因此对它进行了相关资料的查阅并记录如下,希望对大伙在.NET Core中使用有所帮助。

写在前面

您是否曾尝试使用C#代码来实现事务?通常,我们在SQL中一次执行多个Insert / Update语句的话可能就会使用到事务。事务遵循ACID(原子性,一致性,隔离性,持久性)规则,这样所有的语句要么全部执行成功要么全部被取消并执行回滚操作。 而我们今天要讲的TransactionScope则可以允许我们在应用程序级别实现这个过程。在某些情况下,您可能需要在同一个数据库甚至多个数据库(分布式事务)中执行不同的操作,或者由于某些其他约束,它无法在数据库级别来完成,或者应用程序的开发人员对数据库的接触较少,那么这时候TransactionScope将会让你游刃有余。

什么是TransactionScope呢?

TransactionScope作为System.Transactions的一部分被引入到.NET 2.0。同时SqlClient for .NET Core 从 2.1 及以上版本开始提供对System.Transactions的支持 。 它是一个类,它提供了一种简单的方法,可以将一组操作作为事务的一部分来进行处理,而不必担心场景背后的复杂性。如果某个操作在执行的过程中失败的话,则整个事务将失败并执行回滚操作,从而撤消已完成的所有操作。所有这些都将由框架处理,从而确保数据的一致性。

如何使用TransactionScope呢?

要使用它,您需要添加System.Transactions的引用,如果你使用的是.net core的话。这个引用被包含在netcoreapp2.2\System.Transactions.Local.dll 中, 该引用是框架库的一部分(通常默认情况下不会自动添加)。添加后,在我们想要使用它的地方添加名称空间 System.Transactions即可。代码如下所示:

640?wx_fmt=png

在上面的代码中我们可以看到我们在创建TransactionScope实例时使用了using 语句块及Disposable块,它确保了当dispose离开块并结束事务范围时调用dispose来进行资源的释放。
在一个Transaction范围中,我们可以做多个连接甚至链接到不同数据库的操作的,如下所示:

640?wx_fmt=png

下面我们使用两个不同的数据库连接字符串来连接不同的数据库。当然我们也可以根据我们的业务要求使用尽可能多数据库。我们也可以再事务中嵌套事务。如下代码所示:

640?wx_fmt=png

这里最顶层的事务范围称为根范围。另外这里需要注意的是即使通过调用scope.Complete()完成内部事务(上面的OtherTransaction ,如果由于各种原因无法调用rootscope complete,那么整个事务也将被回滚包括内部的事务。

*注意:执行分布式trsanctions时,您可能会收到以下异常之一*

  1. 服务器上的MSDTC不可用

  2. 已禁用分布式事务管理器(MSDTC)的网络访问。

这两个错误都是由于同样的原因,第一个是在数据库和应用程序是同一个服务器时发生的,而在另一个则是服务跟数据库分别部署在两台服务器上。对于同一台服务器,请转到run-> cmd-> services.msc。运行名为Distributed Transaction Coordinator的服务并自动启动启动类型,以便在系统重新启动时再次启动它。对于2,你可能需要参照这个链接的内容进行相应的设置

TransactionScope 类提供了多个重载构造函数,它们接受 TransactionScopeOption 类型的枚举,而该枚举定义事务范围行为。

TransactionScope对象有以下三个选项:

  • Required:联接环境事务,或者在环境事务不存在的情况下创建新的环境事务。

  • RequiresNew:成为新的根范围,也就是说,启动一个新事务并使该事务成为其自己范围中的新环境事务。

  • Suppress:根本不参与事务。 因此没有环境事务。

如果用 Required] 实例化范围并且存在环境事务,则该范围会联接该事务。 相反,如果不存在环境事务,该范围就会创建新的事务并成为根范围。 这是默认值。 在使用 Required时,无论范围是根范围还是仅联接环境事务,该范围中的代码都不需要有不同的行为。 该代码在这两种情况下的行为应相同。

如果用 RequiresNew 实例化范围,则它始终为根范围。 它会启动一个新事务,并且其事务成为该范围中的新环境事务。

如果用 Suppress 实例化范围,则无论是否存在环境事务,范围都从不参与事务。 始终使用此值实例化的作用域具有null作为其环境事务。

下面来让我们看一组实例代码:

640?wx_fmt=png

在这里,我们使用不同的TransactionScopeOptions在父事务下创建了三个事务。默认情况下,范围是required ,这里父事务就是采用的这个默认参数进行创建的。它是一个创建新事务的根范围,并将其标记为环境事务。scope1也是使用required创建的,因为我们已经有了一个环境事务(范围),所以它加入到父事务中。scope2是使用RequiresNew选项创建的,这意味着它是一个独立于环境事务处理的新事务。scope3是用suppress创建的选项,这意味着它不参与任何环境事务。无论环境事务是否成功执行,它都会被执行。父(全局)范围完成后,将提交所有环境事务。

注意点

  1. EF Core 依赖数据库提供程序以实现对 System.Transactions 的支持。 虽然支持在 .NET Framework 的 ADO.NET 提供程序之间十分常见,但最近才将 API 添加到 .NET Core,因此支持并未得到广泛应用。 如果提供程序未实现对 System.Transactions 的支持,则可能会完全忽略对这些 API 的调用。 SqlClient for .NET Core 从 2.1 及以上版本开始支持 System.Transactions。如果尝试在低版本中 如.NET Core 2.0中尝试使用该功能将引发异常。

  2. 自版本 2.1 起,.NET Core 中的 System.Transactions 实现将不包括对分布式事务的支持,因此不能使用 TransactionScope 或 CommittableTransaction 来跨多个资源管理器协调事务。主要是不依赖windows中的mstsc功能。

  3. 异步方法使用时需要注意:

    在下面的例子中,我们在TransactionScope内部使用await

    usingvar scope = new TransactionScope())
    { var groups = await Context.ProductGroups.ToListAsync()。ConfigureAwait(false); 
    }

    看起来没有问题,但它会抛出一个 System.InvalidOperationException:``A TransactionScope must be disposed on the same thread that it was created.

    原因是默认情况下TransactionScope不会从一个线程切换到另一个线程。为了解决这个问题,我们必须使用 TransactionScopeAsyncFlowOption.Enabled

    usingvar scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    { var groups = await Context.ProductGroups.ToListAsync()。ConfigureAwait(false); 
    }

    现在应该可以了吧?这取决于下面的情况。

    如果我们使用和不使用TransactionScopeAsyncFlowOption这个选项的时候都使用了相同的数据库连接,并且第一次执行的时候没有使用这个选项,那么我们会得到另一个异常: System.InvalidOperationException:``Connection currently has transaction enlisted. Finish current transaction and retry.

    换句话说,由于第一个访问的原因,第二个会话将会失败。如下代码所示:

    640?wx_fmt=png

    想象一下,如果第一个调用是在第三方库或您正在使用的框架中完成的,二您不了解其中的代码 - 如果您之前没有看到此错误,那么你讲无从下手来解决这个问题。


总结

本文带着大家熟悉了一遍TransactionScope并对其使用进行了介绍!同时介绍了在.NET Core中使用TransactionScope的一些注意事项!希望对大家有所帮助。另附上.NET Core实战项目交流群:637326624


您的支持是我持续更新的动力。动动手指,扫描下方二维码关注".NET Core实战"公众号:

640?wx_fmt=jpeg


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

P4548-[CTSC2006]歌唱王国【概率生成函数,KMP】

正题 题目链接:https://www.luogu.com.cn/problem/P4548 题目大意 ttt次询问,给出一个长度为mmm的串SSS和一个空串TTT,每次在TTT后面随机加入1∼n1\sim n1∼n的字符,直到TTT中出现SSS为止,求期望次数。 1≤n≤105,t≤50,1≤m≤10…

YBTOJ:字符匹配(KMP)

文章目录题目描述解析代码题目描述 解析 显然应该要尝试套kmp的板子 关键是如何套 也就是那个判断匹配的条件是什么的问题 本题的关键是当kmp匹配时,匹配位之前的所有位大小关系的顺序都是匹配的,所以我们只需要看当前位即可 考虑对b预处理出3个数组&a…

历史上的今天(history)+ 勇者斗恶龙(dragon)

朋友们我来了,好久都没有更新了,手实在痒痒,不撸两道,内心过意不去 文章目录A:历史上的今天(history)题目题解代码实现B: 勇者斗恶龙(dragon)题目描述题解代…

Codeforces Round #694 Div. 2

Codeforces Round #694 Div. 2 CodeForces 1471A Strange Partition CodeForces 1471B Strange List CodeForces 1471C Strange Birthday Party 签到题 稍有难度 CodeForces 1471D Strange Definition CodeForces 1471E Strange Shuffle CodeForces 1471F Strange Housing

领域驱动设计,让程序员心中有码(四)

#领域驱动设计,让程序员心中有码(四)----------------------追忆有关分层的古老往事我一直认为,程序员也是艺术家,他们撰写的每一行代码,是献给这大好世界的优美诗篇。不同的人,写的代码也许风格…

YBTOJ洛谷P4551:最长异或路径(trie树)

洛谷传送门 文章目录题目描述解析代码题目描述 解析 本题关键就在于一点: 若把每个点的深度dep[i]定义为从根到节点边权的异或和 那么i到j的路径异或和可以表示为: dep[i] ^ dep[j] 首先要是i、j在不同子树上显然成立 如果他们在同一子树上,…

P5074-Eat the Trees【插头dp】

正题 题目链接:https://www.luogu.com.cn/problem/P5074 题目大意 给出一个nmn\times mnm的网格,有的必须铺线有的不能,铺成若干条闭合回路,求方案数。 1≤n,m≤121\leq n,m\leq 121≤n,m≤12 解题思路 考虑插头dpdpdp,因为可以…

初赛—算法复杂度

对于 \(T(n) a\times T(\frac{n}{b})c\times n^k\) 这样的递归关系&#xff0c;有这样的结论&#xff1a; \(a>b^k\) 则有 &#xff1a; \(T(n) O(c\times n^{\log_{b} a})\)\(ab^k\) 则有 &#xff1a; \(T(n) O(c\times n^k\times log n)\)\(a<b^k\) 则有 &#xff…

1414. 牛异或

题意&#xff1a; 区间长度为n的数组a&#xff0c;取连续一段子序列&#xff0c;问哪段子序列的异或和最大&#xff0c;如果存在多个这样的序列&#xff0c;那么选择序列末端整数对应的编号更小的那个序列。 如果仍然存在多个可选的序列&#xff0c;那么选择长度最短的那个序列…

基于Asp.Net Core打造轻量级内部服务治理RPC(一)

继之前的《Asp.Net Core Docker 搭建》文章末尾说过的&#xff0c;将陆续编写基于asp.net core 打造一个内部服务治理的rpc框架。不过前端时间较忙&#xff0c;所以搁置了一段时间。闲话不多说&#xff0c;下面就来讲讲为什么需要去做一个该框架&#xff0c;以及想法的来源和设…

P7046-「MCOI-03」诗韵【SAM,倍增,树状数组】

正题 题目链接:https://www.luogu.com.cn/problem/P7046 题目大意 给出一个长度为 nnn 的字符串&#xff0c;然后 mmm 次把它的一个子串加入集合。如果一个字符串在这个集合中作为字符串的后缀出现次数大于 kkk 那么这个字符串就会被计入贡献。 每次求计入贡献的字符串数和最…

YBTOJ:前缀询问(trie树)

文章目录题目描述解析代码题目描述 解析 &#xff08;没有做出来&#xff0c;这个ans的处理方式其实也不难想…qwq&#xff09; 考虑把T都作为模板串加入trie树 加入每个模板串自然就是按照i顺序的 所以我们在插入t的时候沿途标记一下 新出现的未标记的i的间隔就是当前的i与上…

DP专练1( [NOIP 2003]加分二叉树 + 太空梯 )

我们先慢慢来加分二叉树题目题解简单讲解前序//中序//后序遍历代码实现太空梯题目题解代码实现加分二叉树 题目 题解 简单讲解前序//中序//后序遍历 其实说白了&#xff0c;这个*序就是根root的遍历顺序 先序就是root–>left–>right 中序就是left–>root–>rig…

P1896 [SCOI2005]互不侵犯

P1896 [SCOI2005]互不侵犯 题目&#xff1a; 在NN的棋盘里面放K个国王&#xff0c;使他们互不攻击&#xff0c;共有多少种摆放方案。国王能攻击到它上下左右&#xff0c;以及左上左下右上右下八个方向上附近的各一个格子&#xff0c;共8个格子。 题解&#xff1a; 需要知道…

AT2368-[AGC013B]Hamiltonish Path【构造】

正题 题目链接:https://www.luogu.com.cn/problem/AT2368 题目大意 给出 nnn 个点 mmm 条边的一张无向图&#xff0c;然后求一条路径满足 路径长度不小于二。路径无交。对于所有的 xxx 与路径的端点相连&#xff0c;那么 xxx 在路径上。 1≤n,m≤1051\leq n,m\leq 10^51≤n,…

YBTOJ:运动积分(trie树)

文章目录题目描述解析代码题目描述 解析 做了巨长时间… 进行了一次刺激的阅读理解竞赛… 感谢whh dalao&#xff01; 那么让我们分析一下这道题 首先我们考虑单个求x选手的q值 不难发现 i 在第j天和x的大小关系只与a[x]与a[i]二进制下不同的最高位k有关 j的第k位与x相同时&am…

年终总结,我为什么离开舒适区?

当圣诞夜过去&#xff0c;也意味着这一年即将结束&#xff0c;迎来崭新的开始&#xff0c;一年时间既短暂&#xff0c;又漫长&#xff0c;当离开人生的舒适区&#xff0c;将迎来一个又一个的挑战。如果说一个人的优秀&#xff0c;取决于他天赋&#xff0c;以及他为之付出的额外…

NC16886 炮兵阵地

题目&#xff1a; n*m个网格&#xff0c;有平原&#xff0c;有山地&#xff0c;平原可以放部队&#xff0c;部队攻击范围如图&#xff08;不受地形影响&#xff09;&#xff08;H为山地&#xff0c;P为平原&#xff09; 题解&#xff1a; 确定状态&#xff1a; 因为每个炮可…

CF891B-Gluttony【构造】

正题 题目链接:https://www.luogu.com.cn/problem/CF891B 题目大意 给出nnn个数字互不相同的一个序列aaa&#xff0c;求它的一个排列bbb&#xff0c;使得选出任意一个1∼n1\sim n1∼n的下标真子集&#xff0c;都有aaa的对应下标和不等于bbb的对应下标和。 1≤n≤22,0≤ai≤10…

DP专练2 (大理石 + [ZJOI 2010]数字计数)

你肯定以为DP专练会有很多题&#xff0c; 但是请考虑一下本仙女的DP码力&#xff0c;一次性能更几个题。。。 来吧&#xff0c;别害怕呀~~ 文章目录大理石题目题解代码实现数字计数题目题解代码实现大理石 题目 林老师是一位大理石收藏家&#xff0c;他在家里收藏了n块各种…