c# - .NET TransactionScope 和 MSDTC

标签 c# entity-framework transactions distributed-transactions msdtc

在我的代码中有要处理的事务:

using (var scope = new TransactionScope())
{
  repo1.SaveSomething();
  repo2.SaveAnythingElse();
  scope.Complete();
}

在 repo1 和 repo2 函数内部,通过使用创建它们自己的数据库上下文,并处理它们,事务就像一个魅力。

现在我添加另一个这样的代码,它开始抛出一个异常:

The underlying provider failed on Open. (EntityFramework) Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool. (System.Transactions) The transaction manager has disabled its support for remote/network transactions.

我读到,尽管使用相同的 sql server 相同的数据库,但在事务内部打开连接时 - 它需要 MSDTC 组件来处理它。我将代码更改为以下内容:

using (var scope = new TransactionScope(TransactionScopeOption.Required, 
new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted }))
{
   ....
   scope.Complete();
}

现在异常消失了。

我的问题:

  • 为什么之前在代码中使用的事务从未丢弃异常?
  • 为什么新代码放弃了它?
  • 改变后为什么不再下降了?

我认为是简单的问题 :) 如有任何帮助,我们将不胜感激!

最佳答案

1) 您绝对应该为您的 TransactionScope 使用 ReadCommitted 而不是默认的 Serializable,但这与您的问题无关,请参阅 here .

2) 当您有一个事件的 TransactionScope 时,只要您打开一个 SqlConnection,它就会被加入该事务。如果没有其他资源参与事务,SqlClient 将开始本地或“轻量级”事务。这涉及 MSTDC;它只是在打开的 SqlConnection 上启动的普通 SQL Server 事务。

如果您关闭该 SqlConnection(或 Dispose 一个包含它的 EF DbContext),该连接将返回到连接池。但它与其他池连接隔离开来,只是挂起,直到事务完成或回滚。

如果您在同一个 TransactionScope 中打开一个新的 SqlConnection,完全具有相同的 ConnectionString,连接池不会获取新连接,而是返回已在事务中登记的现有连接.

如果您在同一个 TransactionScope 中使用不同的 ConnectionString 打开一个新的 SqlConnection,或者当连接池中没有连接已经登记在 Transaction 中时,那么您将获得一个新的 SqlConnection 并且它将登记在 Transaction 中.但是由于事务中已经有另一个 SqlConnection,这将需要 MSTDC 创建一个真正的分布式事务。这就是所谓的“促销”;您的“轻量级事务”被“提升”为“分布式事务”。

因此,在该背景下,审核您的连接生命周期和 ConnectionString 使用情况,以了解您为何在此处触发升级。

换句话说,通过正确使用 ConnectionString 和连接生命周期管理,您应该能够运行此代码:

using (var scope = new TransactionScope())
{
  repo1.SaveSomething();
  repo2.SaveAnythingElse();
  scope.Complete();
}

不触发分布式事务。

关于c# - .NET TransactionScope 和 MSDTC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48399623/

相关文章:

spring - 如何配置 glassfish 以使用应用程序托管实体管理器?

C# TcpClient,同时读写流

c# - 反向 IP 域检查?

c# - 不使用模型类直接将 int 发布到 web api

mysql - MySQL 查询中的竞争条件?减少库存

Paypal买家交易号和卖家交易号不同

c# - Visual Studio 单元测试 : run initialization code before each test

c# - Entity Framework 5 - 使用参数调用存储过程。无法识别参数

c# - 如何在 Unity 5 中使用 .NET Framework 4.5

c# - 如何在 Entity Framework Core 中为多对多关系创建第三个表?