【问题标题】:.NET TransactionScope and MSDTC.NET TransactionScope 和 MSDTC
【发布时间】:2018-07-02 03:34:45
【问题描述】:

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

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

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

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

基础提供程序在打开时失败。 (EntityFramework) 网络 分布式事务管理器 (MSDTC) 的访问权限已被禁用。 请在安全配置中为网络访问启用 DTC MSDTC 使用组件服务管理工具。 (System.Transactions) 事务管理器已禁用其支持 用于远程/网络事务。

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

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

现在异常消失了。

我的问题:

  • 为什么前面代码中使用的事务从不丢弃异常?
  • 为什么新代码会删除它?
  • 更改后为什么不再下降?

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

【问题讨论】:

  • 什么数据库?交易促进是依赖于提供者的行为。
  • MS-Sql 服务器,兼容级别 SQL Server 2012 (110)。

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


【解决方案1】:

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

2) 当你有一个活动的 TransactionScope 时,任何时候你打开一个 SqlConnection,它都会被加入到那个 Transaction 中。如果没有其他资源参与事务,SqlClient 将开始本地或“轻量级”事务。这涉及 MSTDC;这只是在打开的 SqlConnection 上启动的普通 SQL Server 事务。

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

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

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

因此,在此背景下,审核您的连接生命周期和 ConnectionString 使用情况,以了解您在此处触发促销的原因。

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

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

不触发分布式事务。

【讨论】:

  • 谢谢。我将审查我的代码。所以这意味着“ReadCommitted”不计算在内。然后 - 这是我代码中唯一的变化 - 为什么异常不再下降?
  • "...或者当连接池中没有连接时已经在事务中登记..." - 第 5 段。当创建事务后创建第一个连接?而且我们知道那个不会被提升。
  • 只有在您获得 第二个 连接时才会进行促销。
  • 好的,如果你打开了一个,然后你打开第二个而不关闭第一个,我引用的内容就适用,对吧?顺便说一句,这是我在两天内读到的关于 TransactionScope 的最有用的东西。很难找到谈论细节的像样的材料,所以谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多