为什么TransactionScope不能在实体框架中工作?

时间:2022-03-14 02:31:00

See the code below. If I initialize more than one entity context, then I get the following exception on the 2nd set of code only. If I comment out the second set it works.

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

{"The underlying provider failed on Open."}

{"打开时基础提供者失败。"

Inner: {"Communication with the underlying transaction manager has failed."}

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

Inner: {"Error HRESULT E_FAIL has been returned from a call to a COM component."}

内部:{"Error HRESULT E_FAIL从对COM组件的调用中返回。"

Note that this is a sample app and I know it doesn't make sense to create 2 contexts in a row. However, the production code does have reason to create multiple contexts in the same TransactionScope, and this cannot be changed.

请注意,这是一个示例应用程序,我知道在一行中创建两个上下文是没有意义的。但是,生产代码确实有理由在同一个事务范围中创建多个上下文,这是不能更改的。

Edit

编辑

Here is a previous question of me trying to set up MS-DTC. It seems to be enabled on both the server and the client. I'm not sure if it is set up correctly. Also note that one of the reasons I am trying to do this, is that existing code within the TransactionScope uses ADO.NET and Linq 2 Sql... I would like those to use the same transaction also. (That probably sounds crazy, but I need to make it work if possible).

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

How do I use TransactionScope in C#?

如何在c#中使用TransactionScope ?

Solution

解决方案

Windows Firewall was blocking the connections to MS-DTC.

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

8 个解决方案

#1


18  

Your MS-DTC (Distributed transaction co-ordinator) is not working properly for some reason. MS-DTC is used to co-ordinate the results of transactions across multiple heterogeneous resources, including multiple sql connections.

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

Take a look at this link for more info on what is happening.

看看这个链接,了解更多正在发生的事情。

Basically if you make sure your MS-DTC is running and working properly you should have no problems with using 2 ADO.NET connections - whether they are entity framework connections or any other type.

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

#2


19  

You can avoid using a distributed transaction by managing your own EntityConnection and passing this EntityConnection to your ObjectContext. Otherwise check out these.

通过管理自己的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

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID = 580828 siteid = 1模式= 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();
}

#3


5  

Add C:\Windows\msdtc.exe to the firewall exceptions on both the firewall and server. I spent ages monkeying around opening specific port numbers and ranges to no avail before I did this.

添加C:\Windows\msdtc.防火墙和服务器上的防火墙异常。我花了很长时间在打开特定的端口号和范围上胡思乱想,但在此之前没有任何效果。

#4


4  

I'm going to stick this here because I spent 3 hours with a colleague yesterday debugging this issue. Every single answer surrounding this says that this is always a firewall issue; however in our case it wasn't. Hopefully this will spare someone else the pain.

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

The situation that we have is that we are currently in the process of migrating to the Entity Framework. That means that we have parts of the code where inside a single transaction connections are opened both directly using a new SqlConnection(connectionString).Open() and indirectly by using an EF data context.

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

This has been working fine in our application for a while, but when we started to retrospectively go and put tests around the code that worked in production, the code executed from the test runner kept throwing this error the first time the EF object tried to connect to the database after a direct connection had been made in the same transaction.

这是工作正常在我们的应用程序中,但是当我们开始回顾去把测试在生产工作的代码,代码执行的测试运行器保持抛出这个错误EF对象第一次试图连接到数据库之后直接连接了在相同的事务中。

The cause of the bug eventually turned out to be that if you do not supply an Application Name= argument to your connection string, the Entity Framework adds one by default (something like EntityFrameworkMUF). This means that you have two distinct connections in your connection pool:

导致这个错误的最终原因是,如果您不向您的连接字符串提供应用程序名称=参数,那么实体框架默认添加一个(类似EntityFrameworkMUF)。这意味着在连接池中有两个不同的连接:

  1. The one that you open manually with no Application Name= argument
  2. 您手动打开的没有应用程序名称=参数的那个
  3. An automatically generated one suffixed Application Name=EntityFrameworkMUF
  4. 自动生成一个后缀应用程序名称=EntityFrameworkMUF

and it is not possible to open two distinct connections inside a single transaction. The production code specified an application name; hence it worked; the test code did not. Specifying the Application Name= argument fixed the bug for us.

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

#5


3  

BTW you should consider using SaveChanges(false) in combination with AcceptChanges() when you using Explicit transactions like this.

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

That way if something fails in SaveChanges(false), the ObjectContext hasn't discarded your changes so you can re-apply later or do some error logging etc.

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

See this post for more information: http://blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx

请参阅此帖子获得更多信息:http://blogs.msdn.com/alexj/archive/2009/01/11/savechange -false.aspx。

Cheers

干杯

Alex

亚历克斯

#6


1  

The problem is that 2 different DataContext effectively create two different connections.

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

In that case, the transaction HAS to be promoted to a distributed transaction. I assume your problem comes from the coniguration of MS DTC (Microsoft Distributed Transaction Coordinator) on the server and or the client. If the server is not configured to allow remote connections for MSDTC for example, you will encounter that kind of exception.

在这种情况下,必须将事务提升为分布式事务。我认为您的问题来自于服务器和客户端上的MS DTC (Microsoft Distributed Transaction Coordinator)的默许。例如,如果服务器没有配置为允许MSDTC的远程连接,您将遇到这种异常。

you can refer to this MS page for example for troubleshooting MSDTC problems, and google is filled to the brim with articles/forum questions about it.

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

Now, it might be something else, but it really sounds like it is an MSDTC problem.

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

#7


0  

I've written a answer in another question about how to diagnose MSDTC transactions failing.

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

You might find that answer helpful.

你可能会发现这个答案很有帮助。

How do I enable MSDTC on SQL Server?

如何在SQL服务器上启用MSDTC ?

#8


0  

I did have similar errors occurred when using DTC when reading messages from MQ queue, processing them and storing in SQL 2005 Express Edition database. I haven't enough time to investigate till end whether 2005 or excatly Express edition caused this problem, but switching to 2008 Standard faded that particular behavior out.

在使用DTC从MQ队列读取消息、处理消息并将其存储在SQL 2005 Express Edition数据库时,我确实遇到过类似的错误。我还没有足够的时间去调查到底是2005年还是excatly Express edition造成了这个问题,但是切换到2008 Standard就把这个特殊的行为淡出了。

#1


18  

Your MS-DTC (Distributed transaction co-ordinator) is not working properly for some reason. MS-DTC is used to co-ordinate the results of transactions across multiple heterogeneous resources, including multiple sql connections.

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

Take a look at this link for more info on what is happening.

看看这个链接,了解更多正在发生的事情。

Basically if you make sure your MS-DTC is running and working properly you should have no problems with using 2 ADO.NET connections - whether they are entity framework connections or any other type.

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

#2


19  

You can avoid using a distributed transaction by managing your own EntityConnection and passing this EntityConnection to your ObjectContext. Otherwise check out these.

通过管理自己的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

http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID = 580828 siteid = 1模式= 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();
}

#3


5  

Add C:\Windows\msdtc.exe to the firewall exceptions on both the firewall and server. I spent ages monkeying around opening specific port numbers and ranges to no avail before I did this.

添加C:\Windows\msdtc.防火墙和服务器上的防火墙异常。我花了很长时间在打开特定的端口号和范围上胡思乱想,但在此之前没有任何效果。

#4


4  

I'm going to stick this here because I spent 3 hours with a colleague yesterday debugging this issue. Every single answer surrounding this says that this is always a firewall issue; however in our case it wasn't. Hopefully this will spare someone else the pain.

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

The situation that we have is that we are currently in the process of migrating to the Entity Framework. That means that we have parts of the code where inside a single transaction connections are opened both directly using a new SqlConnection(connectionString).Open() and indirectly by using an EF data context.

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

This has been working fine in our application for a while, but when we started to retrospectively go and put tests around the code that worked in production, the code executed from the test runner kept throwing this error the first time the EF object tried to connect to the database after a direct connection had been made in the same transaction.

这是工作正常在我们的应用程序中,但是当我们开始回顾去把测试在生产工作的代码,代码执行的测试运行器保持抛出这个错误EF对象第一次试图连接到数据库之后直接连接了在相同的事务中。

The cause of the bug eventually turned out to be that if you do not supply an Application Name= argument to your connection string, the Entity Framework adds one by default (something like EntityFrameworkMUF). This means that you have two distinct connections in your connection pool:

导致这个错误的最终原因是,如果您不向您的连接字符串提供应用程序名称=参数,那么实体框架默认添加一个(类似EntityFrameworkMUF)。这意味着在连接池中有两个不同的连接:

  1. The one that you open manually with no Application Name= argument
  2. 您手动打开的没有应用程序名称=参数的那个
  3. An automatically generated one suffixed Application Name=EntityFrameworkMUF
  4. 自动生成一个后缀应用程序名称=EntityFrameworkMUF

and it is not possible to open two distinct connections inside a single transaction. The production code specified an application name; hence it worked; the test code did not. Specifying the Application Name= argument fixed the bug for us.

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

#5


3  

BTW you should consider using SaveChanges(false) in combination with AcceptChanges() when you using Explicit transactions like this.

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

That way if something fails in SaveChanges(false), the ObjectContext hasn't discarded your changes so you can re-apply later or do some error logging etc.

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

See this post for more information: http://blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx

请参阅此帖子获得更多信息:http://blogs.msdn.com/alexj/archive/2009/01/11/savechange -false.aspx。

Cheers

干杯

Alex

亚历克斯

#6


1  

The problem is that 2 different DataContext effectively create two different connections.

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

In that case, the transaction HAS to be promoted to a distributed transaction. I assume your problem comes from the coniguration of MS DTC (Microsoft Distributed Transaction Coordinator) on the server and or the client. If the server is not configured to allow remote connections for MSDTC for example, you will encounter that kind of exception.

在这种情况下,必须将事务提升为分布式事务。我认为您的问题来自于服务器和客户端上的MS DTC (Microsoft Distributed Transaction Coordinator)的默许。例如,如果服务器没有配置为允许MSDTC的远程连接,您将遇到这种异常。

you can refer to this MS page for example for troubleshooting MSDTC problems, and google is filled to the brim with articles/forum questions about it.

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

Now, it might be something else, but it really sounds like it is an MSDTC problem.

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

#7


0  

I've written a answer in another question about how to diagnose MSDTC transactions failing.

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

You might find that answer helpful.

你可能会发现这个答案很有帮助。

How do I enable MSDTC on SQL Server?

如何在SQL服务器上启用MSDTC ?

#8


0  

I did have similar errors occurred when using DTC when reading messages from MQ queue, processing them and storing in SQL 2005 Express Edition database. I haven't enough time to investigate till end whether 2005 or excatly Express edition caused this problem, but switching to 2008 Standard faded that particular behavior out.

在使用DTC从MQ队列读取消息、处理消息并将其存储在SQL 2005 Express Edition数据库时,我确实遇到过类似的错误。我还没有足够的时间去调查到底是2005年还是excatly Express edition造成了这个问题,但是切换到2008 Standard就把这个特殊的行为淡出了。