在Entity Framework事务中使用SqlConnection

3

我有一个使用EF6的项目,它使用了一些旧的库(我不能修改这个库)。我的项目中的代码如下:

Using scope As New TransactionScope()
   //Many DAOs calls that work just nice
   //The call to the legacy library that fails
End Using

在这个库中,代码如下所示:

Using connection As new Sqlconnection("bla")
   connection.Open()  //THIS LINE FAILS INTERMITTENTLY
   //more code
End Using

我已经调整了EF项目的隔离级别和事务范围,但是没有运气,问题仍然存在。在EF事务中手动打开连接是有效的吗?

我得到的异常为:

操作对于事务的状态无效

或者

与底层事务管理器的通信失败。 2014-10-11 13:49:16,736 ERROR[DataAccess.Services]: Timbrar: 该操作对于事务的状态无效。 内部异常:由于通信问题,MSDTC事务管理器无法从源事务管理器中拉取事务。可能的原因是:防火墙存在且没有为MSDTC进程设置例外,两台计算机无法通过其NetBIOS名称找到彼此,或者其中一个事务管理器未启用网络事务的支持。(HRESULT异常代码:0x8004D02B) 2014-10-11 13:49:16,767 ERROR[DataAccess.Services]: at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction) at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification) at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) at System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource1 retry, DbConnectionOptions userOptions) at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource1 retry) at System.Data.SqlClient.SqlConnection.Open() at GuardarBitacora(String sCnn, Int64 CtePrincipalID, String NombreArchivos, String numUUID, String Proveedor, Int32 EstatusOper, String MensajeFolio, String MensajeErrorMetodo) at CoreGenWS(String pstrXml, String usuario, String rfc, String password, Boolean sello, Boolean test) at GenArchivoWS(String usuario, String rfc, String password, Byte[] xml, Boolean sello, Boolean test) at Func(String usuario, String rfc, Int64 pCtePrincipalId, Boolean pftest, Byte[] xml, String pwdFac) at Services.Func(RazonSocial razonSocial, Byte[] xmlValido) at Services.(Boolean esBorrador, Int64 usuarioId, , encabezado, , List1 detalles, Func1 , Func3 , Func1 , Func`2 )
我已经仔细检查了msdtc服务。它在两台服务器上都被正确地配置了,但奇怪的是,只有在系统负载较高时才会出现这种情况。

这种情况只会在系统负载较高时偶尔发生。连接池更喜欢返回最先参与当前事务的连接。这意味着通常不需要使用 MSDTC。也就是说,只有在负载较高时才可能出现这种情况。(我不知道这个错误的原因。) - usr
@usr 是的和不是的。问题完全与 MSDTC 相关,但我认为它总是被使用的,因为如果服务被禁用,代码的这一部分总是会失败,无论负载是重还是轻。为什么 MSDTC 间歇性地失败?这是个大谜团。 - rsan
1
不能告诉你...我严格避免接触MSDTC。它真的是个麻烦制造者。(而且你知道它不能与镜像和AG一起使用,对吧?祝你制定高可用性计划愉快。) - usr
1
+1 对于“它真的是个麻烦制造者”的认同 :) - rsan
1个回答

1
我找到了解决方法(或多或少)。问题是EntityFramework无法将第二个连接加入同一事务中,并将其升级为由MSDTC服务管理的分布式事务。
这是因为即使所有连接都连接到同一个数据库,某些连接也是使用不同的连接字符串进行连接。解决方法是为所有连接使用相同的连接字符串,并在此连接字符串中设置Application Name属性。之后,我能够禁用MSDTC服务,并且应用程序始终能够正常工作而不会出现异常。即使我们的系统负载很重。
这里是救星帖子: http://joeknowsdotnet.wordpress.com/2012/07/19/entity-framework-msdtc-gotchya/ 我的应用程序正常工作,生活很愉快,但我仍然不知道为什么在使用共享事务时MSDTC有时会失败...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接