为什么TransactionScope不能与Entity Framework一起使用?

请参阅下面的代码。 如果我初始化多个实体上下文,那么我第二组代码上得到以下exception。 如果我注释掉第二组就行了。

{“底层提供商在Open上失败。”}

内部:{“与底层事务管理器的通信失败。”}

内部:{“错误HRESULT E_FAIL已从调用COM组件返回。”}

请注意,这是一个示例应用程序,我知道连续创建2个上下文没有意义。 但是,生产代码确实有理由在同一个TransactionScope创建多个上下文,并且无法更改。

编辑

这是我之前尝试设置MS-DTC的问题。 似乎在服务器和客户端上都启用了它。 我不确定它是否设置正确。 另请注意,我尝试这样做的原因之一是TransactionScope中的现有代码使用ADO.NET和Linq 2 Sql …我希望那些也使用相同的事务。 (这可能听起来很疯狂,但如果可能,我需要让它工作)。

如何在C#中使用TransactionScope?

Windows防火墙阻止了与MS-DTC的连接。

 using(TransactionScope ts = new System.Transactions.TransactionScope()) { using (DatabaseEntityModel o = new DatabaseEntityModel()) { var v = (from s in o.Advertiser select s).First(); v.AcceptableLength = 1; o.SaveChanges(); } //-> By commenting out this section, it works using (DatabaseEntityModel o = new DatabaseEntityModel()) { //Exception on this next line var v = (from s1 in o.Advertiser select s1).First(); v.AcceptableLength = 1; o.SaveChanges(); } //-> ts.Complete(); } 

您的MS-DTC(分布式事务协调器)由于某种原因无法正常工作。 MS-DTC用于协调跨多个异构资源的事务结果,包括多个sql连接。

请查看此链接 ,了解有关正在发生的事情的更多信息。

基本上,如果您确保MS-DTC正在运行并且正常工作,那么使用2个ADO.NET连接应该没有问题 – 无论它们是entity framework连接还是任何其他类型。

您可以通过管理自己的EntityConnection并将此EntityConnection传递给ObjectContext来避免使用分布式事务。 否则看看这些。

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=580828&SiteID=1&mode=1 http://forums.microsoft.com/msdn/showpost.aspx?postid=113669&siteid=1&sb=0&d=1&at=7&ft = 11&TF = 0&的pageid = 1

 EntityConnection conn = new EntityConnection(ConnectionString); using (TransactionScope ts = new TransactionScope()) { using (DatabaseEntityModel o = new DatabaseEntityModel(conn)) { var v = (from s in o.Advertiser select s).First(); v.AcceptableLength = 1; } //-> By commenting out this section, it works using (DatabaseEntityModel o = new DatabaseEntityModel(conn)) { //Exception on this next line var v = (from s1 in o.Advertiser select s1).First(); v.AcceptableLength = 1; } //-> ts.Complete(); } 

将C:\ Windows \ msdtc.exe添加到防火墙和服务器上的防火墙例外。 在我这样做之前,我花了很多年的时间来打开特定的端口号和范围无济于事。

我打算坚持这个,因为我昨天和同事一起花了3个小时来调试这个问题。 围绕此问题的每一个答案都表明这始终是防火墙问题; 但在我们的情况下,它不是。 希望这会让别人感到痛苦。

我们的情况是我们目前正在迁移到entity framework。 这意味着我们有部分代码,其中单个事务连接内部直接使用new SqlConnection(connectionString).Open()并通过使用EF数据上下文间接new SqlConnection(connectionString).Open()

这在我们的应用程序中已经工作了一段时间了,但是当我们开始回顾性地围绕在生产中工作的代码进行测试时,从测试运行器执行的代码在EF对象第一次尝试连接时不断抛出此错误在同一事务中进行直接连接到数据库。

错误的原因最终certificate,如果您不为连接字符串提供Application Name=参数,则entity framework默认添加一个(类似于EntityFrameworkMUF )。 这意味着您的连接池中有两个不同的连接:

  1. 您手动打开但没有Application Name=参数的那个
  2. 自动生成的一个后缀Application Name=EntityFrameworkMUF

并且无法在单个事务中打开两个不同的连接。 生产代码指定了应用程序名称; 因此它有效; 测试代码没有。 指定Application Name=参数修复了我们的错误。

顺便说一句,当您使用像这样的显式事务时,您应该考虑将SaveChanges(false)与AcceptChanges()结合使用。

这样,如果SaveChanges(false)中的某些内容失败,ObjectContext就不会丢弃您的更改,因此您可以稍后重新应用或执行一些错误记录等。

有关更多信息,请参阅此post: http : //blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx

干杯

亚历克斯

问题是2个不同的DataContext有效地创建了两个不同的连接。

在这种情况下,事务HAS将被提升为分布式事务。 我假设您的问题来自服务器和/或客户端上的MS DTC(Microsoft分布式事务处理协调器)的配置。 例如,如果服务器未配置为允许MSDTC的远程连接,则会遇到此类exception。

你可以参考这个MS页面 ,例如MSDTC问题的故障排除,谷歌填补了文章/论坛有关它的问题。

现在,它可能是其他东西,但它听起来确实是MSDTC问题。

我在另一个关于如何诊断MSDTC事务失败的问题中写了一个答案。

您可能会发现该答案很有帮助。

如何在SQL Server上启用MSDTC?

在从MQ队列读取消息,处理它们并存储在SQL 2005 Express Edition数据库中时,我确实发生了类似的错误。 我没有足够的时间去调查,直到2005年或者激动的Express版本是否引起了这个问题,但是切换到2008 Standard已经消除了这种特殊的行为。