作者:依乐祝

原文链接: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即可。代码如下所示:

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

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

这里最顶层的事务范围称为根范围。另外这里需要注意的是即使通过调用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作为其环境事务。

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

在这里,我们使用不同的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

    using(var 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

    using(var 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.

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

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

总结

本文带着大家熟悉了一遍TransactionScope并对其使用进行了介绍!同时介绍了在.NET Core中使用TransactionScope的一些注意事项!希望对大家有所帮助.

transactionscope 中的异步 处理 异常_.NET Core中TransactionScope事务处理方法介绍及注意事项...相关推荐

  1. transactionscope 中的异步 处理 异常_协程中的取消和异常 | 异常处理详解

    开发者们通常会在打磨应用的正常功能上花费很多时间,但是当应用出现一些意外情况时,给用户提供合适的体验也同样重要.一方面来讲,对用户来说,目睹应用崩溃是个很糟糕的体验:而另一方面,在用户操作失败时,也必 ...

  2. java中什么是运行异常_在java中最常用的运行时异常是什么?

    我从不会抛出NullPointerException.对我来说,它是一个出现在代码中当出现问题时,需要开发人员看看会发生什么.然后(s)他固定的原因,它不会再次发生. 我使用IllegalStateE ...

  3. 计算机网络设置中的网关是什么设备,网关是什么_网关的作用与设置方法介绍 一看就明白...

    网关是什么?对于普通的用户来说,电脑网关不是很明白的,不过接触电脑多了之后,大家也会常常会听到"网关"这个词,那么问题就来了,这个网关是什么意思呢?它又有哪些作用呢?今晚,智能手机 ...

  4. .net mysql transactionscope_TransactionScope事务处理方法介绍及.NET Core中的注意事项

    原标题:TransactionScope事务处理方法介绍及.NET Core中的注意事项 作者:依乐祝 原文链接:https://www.cnblogs.com/yilezhu/p/10170712. ...

  5. Linux环境中堆栈和堆相关内存损坏的基本原理和调试方法介绍

    本文讲的是Linux环境中堆栈和堆相关内存损坏的基本原理和调试方法介绍, 前言 建议阅读本文之前,你对ARM组件的有个基本了解,本文会先为你介绍32位Linux环境中进程的内存布局,然后再介绍堆栈和堆 ...

  6. TIA博途S7-1200中实现高低字节或高低字调换的几种方法介绍

    TIA博途S7-1200中实现高低字节或高低字调换的几种方法介绍 例如S7-1200与某些上位机进行通信时,读写的浮点数的存储方式与上位机不同,即高低字或字节是相反的,此时读取的数据是不对的,需要将高 ...

  7. 诛仙3怎么一直服务器维护,诛仙3游戏老是掉线怎么办_诛仙3游戏掉线解决方法介绍...

    诛仙3游戏老是掉线怎么办_诛仙3游戏掉线解决方法介绍 诛仙3经常掉线但又不是网速的锅,通常玩家们会把锅甩给服务器,但是甩锅依然解决不了掉线问题,今天小编为各位玩家带来诛仙3游戏掉线怎么办解决方法,一起 ...

  8. java异常_聊聊Java中的异常及处理

    前言 在编程中异常报错是不可避免的.特别是在学习某个语言初期,看到异常报错就抓耳挠腮,常常开玩笑说编程1分钟,改bug1小时.今天就让我们来看看什么是异常和怎么合理的处理异常吧! 异常与error介绍 ...

  9. java 异常处理发生异常_处理Java中的异常

    java 异常处理发生异常 每个程序员都希望编写一个完美的程序. 也就是说,程序运行时没有任何障碍. 好吧,如果希望是马,乞g就会骑. 除了程序员的所有愿望之外,有时还会发生无法预料的情况. 在Jav ...

最新文章

  1. App 运营的指标具体都有哪些?(二)
  2. 3704对象关闭时_JVM 通过逃逸分析就能让对象在栈上分配?没那么简单!
  3. 使用wlan接收器经常重新登录怎么办
  4. 传统公司部署OpenStack(t版)简易介绍(八)——Dashboard模块部署
  5. MATLAB中,信号的频谱图该怎么绘制?横坐标如何标注出频率值?
  6. 蜜罐网络(开源汇总)MHN
  7. 网关策略跟计算机名有关系吗,交换机网关与与之相连的计算机的网关有没有必然关系...
  8. C语言把浮点数转换为字符串
  9. 【Python】模块学习之Timer定时任务,递归定时自调获取博客浏览量
  10. 基于Java的Cplex入门
  11. 【多元统计分析】11.回归方程与回归系数的显著性检验
  12. 【调剂】上海应用技术大学2021年硕士研究生招生考试调剂信息
  13. tplink710n无线打印服务器,tplink710n设置
  14. 详细讲解半加器、全加器、四位全加器,并使用FPGA实现半加器、全加器
  15. spark sample采样
  16. xp大容量u盘补丁_u盘128g 个性 大容量电脑系统修复
  17. 基于java的个人日程管理系统mysql
  18. 利用百度ocr识别验证码
  19. 用HTML写一首诗并配上图片,需要满足诗的格式
  20. ddz指标最佳数值_大单分差指标ddz如何解析资金流向与筹码分布

热门文章

  1. 酷!一键构建我自己的PHP框架的开发环境
  2. nagios监控+pnp4出图
  3. 浅谈利用SQLite存储离散瓦片的思路和实现方法
  4. ViewPager的缓存机制
  5. 网页html文档头部声明的两种常用模式
  6. 敏捷团队迭代交付能力计算模型
  7. 极客新闻——15、软件测试自动化的最新趋势
  8. RH系列linux上编译android2.3(gingerbread)
  9. Leangoo看板工具做敏捷故事地图看板示例
  10. TCP 为什么是三次握手,而不是两次或四次?