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

Not*_*Dan 25 .net c# entity-framework transactions transactionscope

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

{"底层提供商在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();
        }
Run Code Online (Sandbox Code Playgroud)

小智 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();
}
Run Code Online (Sandbox Code Playgroud)

  • +1用于避免DTC.并不是说它很糟糕,只是分布式交易不能轻易选择.它是应用程序和资源的紧密链接,存在设计可用性低的风险. (6认同)

Ste*_*ock 19

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

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

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

  • 这现在有效.Windows防火墙阻止了与MS-DTC的连接. (4认同)

bur*_*ide 5

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


bri*_*ler 5

我将把它放在这里,因为昨天我和一位同事花了 3 个小时来调试这个问题。围绕这个问题的每个答案都表明这始终是防火墙问题;但在我们的例子中却并非如此。希望这能让其他人免受痛苦。

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

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

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

  1. Application Name=您手动打开且不带参数的那个
  2. 自动生成的后缀Application Name=EntityFrameworkMUF

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