26

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

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

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

内部:{“错误 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();
        }
4

8 回答 8

19

您可以通过管理您自己的 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();
}
于 2009-04-27T18:48:15.800 回答
19

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

查看此链接以获取有关正在发生的事情的更多信息。

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

于 2009-04-27T18:54:21.947 回答
5

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

于 2009-05-06T09:29:54.273 回答
4

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

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

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

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

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

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

于 2013-03-29T09:05:34.060 回答
3

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

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

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

干杯

亚历克斯

于 2009-05-02T00:06:46.297 回答
1

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

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

例如,您可以参考这个 MS 页面来解决 MSDTC 问题,并且谷歌充满了关于它的文章/论坛问题。

现在,它可能是别的东西,但听起来确实是一个 MSDTC 问题。

于 2009-04-27T18:53:19.453 回答
0

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

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

如何在 SQL Server 上启用 MSDTC?

于 2009-04-27T19:24:37.490 回答
0

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

于 2010-04-03T03:29:16.643 回答