.NET TransactionScope和MSDTC [英] .NET TransactionScope and MSDTC

查看:47
本文介绍了.NET TransactionScope和MSDTC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

In my code there are transactions to handle:

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

在repo1和repo2函数内部,使用事务来处理它们,并创建它们自己的db上下文,并将它们处置起来就像是一种魅力.

Inside repo1 and repo2 functions create their own db context with using, and dispose them, the transactions worked like a charm.

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

Now I add another code like this, and it begins to drop an exception:

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

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和同一个db中,在事务内部打开连接时-它需要MSDTC组件来处理它.我将代码更改为以下内容:

I read that when connections are opened inside transaction despite of the same sql server same db - it needs the MSDTC component to handle it. I changed the code to the following:

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

现在异常消失了.

我的问题:

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

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

Easy questions I think :) Any help would be appreciated!

推荐答案

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

1) You absolutely should use ReadCommitted over the default Serializable for you TransactionScope, but that's unrelated to your issue, see here.

2)当您有一个活动的TransactionScope时,无论何时打开SqlConnection,它都会在该Transaction中登记.如果没有其他资源参与事务,则SqlClient将开始本地或轻量级"事务.这不涉及MSTDC;这只是在打开的SqlConnection上启动的普通SQL Server事务.

2) When you have an active TransactionScope, any time you open a SqlConnection it will be enlisted in that Transaction. If there are no other resources participating in the Transaction, SqlClient will begin a local, or "lightweight" transaction. This does not involve MSTDC; it's just a normal SQL Server transaction started on the open SqlConnection.

如果关闭该SqlConnection(或处置包含它的EF DbContext),则该连接将返回到连接池.但是它与其他合并的连接隔离开来,一直挂到事务完成或回滚为止.

If you close that SqlConnection (or Dispose an EF DbContext that contains it), the connection is returned to the connection pool. But it's segregated from the other pooled connections, and just hangs out until the Transaction is Completed or Rolled back.

如果您在相同的TransactionScope中使用完全相同的 打开一个新的SqlConnection,而不是获取新的连接,连接池只会为您提供已在事务中登记的现有连接

If you open a new SqlConnection within the same TransactionScope, with exactly the same ConnectionString, instead of getting a new connection the connection pool just gives you back the existing connection that is already enlisted in the Transaction.

如果在同一TransactionScope中使用不同的ConnectionString打开新的SqlConnection,或者在事务中已经征用的连接池中没有连接,则您将获得一个新的SqlConnection并将其征入事务中.但是,由于在事务中已经存在另一个SqlConnection,因此这将要求MSTDC创建一个真正的分布式事务.这就是所谓的促销";您的轻型交易"被提升"为分布式交易".

If you open a new SqlConnection within the same TransactionScope with a different ConnectionString, or when there is not a connection in the connection pool already enlisted in the Transaction, then you will get a new SqlConnection and it will be enlisted in the Transaction. But since there's already another SqlConnection enlisted in the Transaction, this will require MSTDC to create a real Distributed Transaction. This is called "promotion"; your "lightweight transaction" is "promoted" to a "distributed transaction".

因此,在此背景下,请审核您的连接寿命和ConnectionString的使用情况,以了解为什么在此处触发升级.

So with that background, audit your connection lifetime and ConnectionString usage to see why you are triggering promotion here.

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

In other words, with proper ConnectionString usage and connection lifetime management you should be able to run this code:

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

不触发分布式事务.

这篇关于.NET TransactionScope和MSDTC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆