【问题标题】:Why doesn't TransactionScope work with Entity Framework?为什么 TransactionScope 不能与实体框架一起使用?
【发布时间】:2009-04-27 18:33:43
【问题描述】:

请参阅下面的代码。如果我初始化了多个实体上下文,那么我会在仅在第二组代码上得到以下异常。如果我注释掉第二组,它会起作用。

{“底层提供程序在打开时失败。”}

Inner: {"与底层事务管理器的通信失败。"}

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

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

编辑

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

How do I use TransactionScope in C#?

解决方案

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();
        }

【问题讨论】:

    标签: c# .net entity-framework transactions transactionscope


    【解决方案1】:

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

    查看this link 了解更多信息。

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

    【讨论】:

    • 现在可以使用了。 Windows 防火墙阻止了与 MS-DTC 的连接。
    【解决方案2】:

    您可以通过管理自己的 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();
    }
    

    【讨论】:

    • 我不只是使用实体框架,所以重用 EntityConnection 也不是一个简单的解决方案(见上面的编辑)
    • +1 用于避免 DTC。并不是说它不好,只是分布式事务不是可以轻易选择的东西。它是应用程序和资源的紧密联系,设计上存在可用性低的风险。
    • 也可以调用 context.Connection.Open() 手动管理。您不需要手动创建 EntityConnection
    • 我不明白——你展示了一个 EntityConnection 的例子,所以它应该可以工作,但它失败了。那么这是如何解决的呢?
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      我将把它贴在这里,因为我昨天和一位同事花了 3 个小时来调试这个问题。围绕这个问题的每一个答案都表明这始终是一个防火墙问题。但是在我们的情况下它不是。希望这可以减轻其他人的痛苦。

      我们目前的情况是我们正在迁移到实体框架。这意味着我们有部分代码在单个事务中直接使用 new SqlConnection(connectionString).Open() 打开和间接使用 EF 数据上下文打开。

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

      最终导致该错误的原因是,如果您没有为连接字符串提供Application Name= 参数,实体框架会默认添加一个(类似于EntityFrameworkMUF)。这意味着您的连接池中有两个不同的连接:

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

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

      【讨论】:

      • 我的问题更具体,一个连接字符串使用App=EntityFramework,另一个使用Application Name = EntityFramework。如果这是您的问题,最好的测试方法是从一个上下文中复制连接字符串,并在创建第二个上下文时将其作为参数传递。
      【解决方案5】:

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

      这样,如果 SaveChanges(false) 中出现问题,ObjectContext 不会丢弃您的更改,因此您可以稍后重新应用或进行一些错误记录等。

      更多信息请看这篇文章:http://blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx

      干杯

      亚历克斯

      【讨论】:

        【解决方案6】:

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

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

        您可以参考this MS page,例如解决 MSDTC 问题,谷歌上充斥着关于它的文章/论坛问题。

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

        【讨论】:

        • 见我上面的编辑。我认为您是对的,我正在尝试设置 MS-DTC...我不确定它为什么不起作用。
        【解决方案7】:

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

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

        How do I enable MSDTC on SQL Server?

        【讨论】:

          【解决方案8】:

          我在使用 DTC 从 MQ 队列读取消息、处理它们并将其存储在 SQL 2005 Express Edition 数据库中时确实发生了类似的错误。我没有足够的时间来调查到底是 2005 版还是 excatly Express 版导致了这个问题,但是切换到 2008 标准版会淡化这种特殊行为。

          【讨论】:

            猜你喜欢
            • 2016-03-09
            • 2021-06-14
            • 1970-01-01
            • 1970-01-01
            • 2023-03-11
            • 2016-11-05
            • 2012-09-25
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多