ADO.NET 实体框架中事务的 MSDTC 问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1611950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 13:29:22  来源:igfitidea点击:

MSDTC issue with transactions in ADO.NET Entity Framework

.nettransactionsado.net-entity-data-modelmsdtc

提问by Alexander

in our current project we are using ADO.NET Entity Framework as data layer for the application. There are some tasks which require to run in a transaction because there's a lot of work to do in the database. I am using a TransactionScopeto surround those tasks.

在我们当前的项目中,我们使用 ADO.NET Entity Framework 作为应用程序的数据层。有一些任务需要在事务中运行,因为数据库中有很多工作要做。我正在使用TransactionScope来围绕这些任务。

using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    // Do something...
    transactionScope.Complete();
}

The problem is as soon as i am using an TransactionScopean exception occurs:

问题是一旦我使用TransactionScope就会发生异常:

System.Data.EntityException: The underlying provider failed on Open. ---> System.Transactions.TransactionManagerCommunicationException: Communication with the underlying transaction manager has failed. ---> System.Runtime.InteropServices.COMException (0x80004005): Error HRESULT E_FAIL has been returned from a call to a COM component.

System.Data.EntityException:底层提供程序在打开时失败。---> System.Transactions.TransactionManagerCommunicationException: 与底层事务管理器的通信失败。---> System.Runtime.InteropServices.COMException (0x80004005): 调用 COM 组件时返回了错误 HRESULT E_FAIL。

It seems that this error has to do something with the MSDTC(Microsoft Distributed Transaction Coordinator). When I change the security configuration of MSDTC another exception is thrown:

似乎此错误与MSDTC(Microsoft 分布式事务协调器)有关。当我更改 MSDTC 的安全配置时,会引发另一个异常:

System.Data.EntityException: The underlying provider failed on Open. ---> System.Transactions.TransactionManagerCommunicationException: 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.Data.EntityException:底层提供程序在打开时失败。---> System.Transactions.TransactionManagerCommunicationException:分布式事务管理器 (MSDTC) 的网络访问已被禁用。请使用组件服务管理工具在 MSDTC 的安全配置中为网络访问启用 DTC。

However MSDTC is configured, the TransactionScopewill cause an error. Does somebody know whats going wrong here?

不管 MSDTC 是如何配置的,TransactionScope都会导致错误。有人知道这里出了什么问题吗?

采纳答案by Alexander

Hmm, it seems to work when i change the TransactionScopeOptionto "Suppress":

嗯,当我将TransactionScopeOption更改为“抑制”时,它似乎有效:

using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Suppress))
{
    ...
}

Does everyone know why?

大家知道为什么吗?

回答by Nikolay R

By default MSDTC has network access disabled. To get it working you should go to

默认情况下,MSDTC 已禁用网络访问。为了让它工作,你应该去

Control Panel-> Administrative Tools->Component Services->Component Serivces->Computes->My computer->Right click->Properties->MSDTC->Security Configuration

控制面板->管理工具->组件服务->组件服务->计算->我的电脑->右键->属性->MSDTC->安全配置

and check following checkboxes Network DTC Access, Allow Inbound, Allow Outbound.Authentification should be chosen according to you environment. You might also want to take a look at DTCPingtool to debug distributed transactions. To give you a shortcut - you may need to modify you registry:

并选中以下复选框网络 DTC 访问、允许入站、允许出站。应根据您的环境选择身份验证。您可能还想查看DTCPing工具来调试分布式事务。给你一个快捷方式 - 你可能需要修改你的注册表:

HKLM\Software\Policies\Microsoft\Windows NT\RPCRestrictRemoteClients=0 HKLM\Software\Policies\Microsoft\Windows NT\RPCEnableAuthEpResolution=1

HKLM\Software\Policies\Microsoft\Windows NT\RPCRestrictRemoteClients=0 HKLM\Software\Policies\Microsoft\Windows NT\RPCEnableAuthEpResolution=1

to get everything up and running.

使一切正常运行。

回答by Bill

Yes, it works using Supress, because you are telling it to supress or ignore the ambient transaction and create a new local transaction. Since the transaction is local it is not a distributed transaction so its not using MSDTC, but you probably shouldn't use Suppress and should use Required instead.

是的,它使用 Supress 工作,因为您告诉它抑制或忽略环境事务并创建一个新的本地事务。由于事务是本地事务,因此它不是分布式事务,因此不使用 MSDTC,但您可能不应该使用 Suppress,而应该使用 Required。

回答by Jim Chen

"If you are using Entity Framework with Transactions, Entity Framework automatically opens and closes a connection with each database call. So when using transactions, you are attempting to spread a transaction out over multiple connections. This elevates to MSDTC."

“如果您将 Entity Framework 与事务一起使用,Entity Framework 会自动打开和关闭与每个数据库调用的连接。因此,在使用事务时,您试图将事务分散到多个连接上。这会提升到 MSDTC。”

You can pass in your database context to callee class or function in your transaction.

您可以将数据库上下文传递给事务中的被调用者类或函数。

Maybe this is your answer: MSSQL Error 'The underlying provider failed on Open'

也许这就是您的答案:MSSQL 错误“底层提供程序在打开时失败”

回答by Bram Van Strydonck

Supressing the transaction is usefull if you want to run some code that might fail, but you don't want to abort the transaction because of that fail.

如果您想运行一些可能会失败的代码,但又不想因为该失败而中止事务,那么抑制事务会很有用。

The question you need to ask yourself is the following: Are you accessing more than 1 durable resource in your transactionScope? I mean, do you open connections to more than 1 DB?

您需要问自己的问题如下:您是否在您的 transactionScope 中访问了 1 个以上的持久资源?我的意思是,您是否打开了与 1 个以上 DB 的连接?

This is an important question as the transaction will be escalated towards DTC if you access more than 1 durable resource.

这是一个重要的问题,因为如果您访问 1 个以上的持久资源,事务将升级为 DTC。

At least two durable resources that support single-phase notifications are enlisted in the transaction. For example, enlisting a single connection with does not cause a transaction to be promoted. However, whenever you open a second connection to a database causing the database to enlist, the System.Transactions infrastructure detects that it is the second durable resource in the transaction, and escalates it to an MSDTC transaction.Source: MSDN

事务中至少征用了两个支持单阶段通知的持久资源。例如,登记单个连接不会导致事务被提升。但是,每当您打开与数据库的第二个连接导致数据库登记时,System.Transactions 基础结构会检测到它是事务中的第二个持久资源,并将其升级为 MSDTC 事务。来源:MSDN

If that's the case, you can solve your problem by nesting your transactionscopes correctly, example:

如果是这种情况,您可以通过正确嵌套事务范围来解决问题,例如:

//Create rootScope
using(TransactionScope rootScope = new TransactionScope()) 
{ 
    using(TransactionScope scope2 = new 
    TransactionScope(TransactionScopeOption.Required)) 
    {
         //Do work on DB1
         ...

         //Complete this ambient transaction
         scope2.Complete();
    } 

    using(TransactionScope scope3 = new 
    TransactionScope(TransactionScopeOption.Required)) 
    {
         //Do work on DB2
         ...

         //Complete this ambient transaction
         scope3.Complete();
    } 

    //Complete rootScope
    //The whole transaction will only be committed if you call 
    //Complete on the rootScope
    rootScope.Complete();

}

}

You can find more info about TransactionScopes, how nesting works,... on MSDN.

您可以在MSDN上找到有关 TransactionScopes、嵌套如何工作等的更多信息。

I hope this answer can help people in the future.

我希望这个答案可以在未来帮助人们。

回答by aydnahmet

If Distributed Transaction Coordinator service is not started, Entity framework can not connect to database. Open and start the Distributed Transaction Coordinator

如果分布式事务协调器服务未启动,实体框架将无法连接到数据库。打开并启动分布式事务协调器

Services -> Distributed Transaction Coordinator

服务 -> 分布式事务协调器

回答by SpockMonster

This means it is suppressing any Transaction that might be in effect currently when you enter your code block, so any updates your code makes will not rollback if the outer "ambient" transaction decides to rollback.

这意味着当您输入代码块时,它会抑制当前可能有效的任何事务,因此如果外部“环境”事务决定回滚,则您的代码所做的任何更新都不会回滚。

回答by John Allers

This is the article we used in resolving our own, similar issue:

这是我们用来解决我们自己的类似问题的文章:

Troubleshooting Problems with MSDTC

对 MSDTC 问题进行故障排除

This is basically an addendum to Nikolay R'sanswer. He already covered some of the suggestions listed in the article.

这基本上是Nikolay R答案的附录。他已经涵盖了文章中列出的一些建议。

Note: The article is part of the Biztalk documentation, but it can apply to anything using MSDTC.

注意:该文章是 Biztalk 文档的一部分,但它可以应用于任何使用 MSDTC 的内容。