2009-04-27 85 views
24

请参阅下面的代码。如果我初始化多个实体上下文,那么我在第二组代码上得到以下例外。如果我注释掉第二组,它就可以工作。为什么TransactionScope不能与实体框架一起使用?

{ “底层提供对打开失败。”}

内:{ “与基础事务管理器通信失败。”}

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

回答

18

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

查看this link以了解正在发生的更多信息。

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

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

我不只是使用实体框架,因此重复使用EntityConnection也不是一个简单的解决方案(请参阅上面的编辑) – NotDan 2009-04-27 19:01:07

+6

+1用于避免DTC。这并不是坏事,只是分布式交易不是轻易选择的东西。这是应用程序和资源的紧密链接,可能会降低设计的可用性。 – 2009-04-27 19:48:43

+0

您也可以调用context.Connection.Open()手动管理它。你不需要手动创建EntityConnection – 2009-12-24 16:41:23

1

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

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

例如,您可以参考this MS page来排除MSDTC问题,并且Google会向文章/论坛提问。

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

3

BTW你应该考虑结合使用的SaveChanges(假)用的AcceptChanges在使用你喜欢这个明确的交易()。如果

这样东西的SaveChanges(假)失败,则ObjectContext的还没有放弃你的更改,以便以后可以重新申请或者做一些错误记录等

看到这个职位的详细资料:http://blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx

干杯

亚历

5

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

0

从MQ队列中读取消息,处理它们并存储在SQL 2005 Express Edition数据库中时,使用DTC时发生过类似的错误。我没有足够的时间来调查2005年底或者令人兴奋的Express版造成这个问题,但切换到2008年Standard将这种特殊行为淡化了出来。

4

我打算在这里坚持下去,因为昨天我和同事一起花了3个小时来调试这个问题。围绕这个问题的每一个答案都表明,这总是一个防火墙问题。但在我们的情况下,它不是。希望这会使其他人免于痛苦。

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

这在我们的应用程序中一直运行良好,但是当我们开始回溯并将测试放在生产中的代码周围时,从测试运行器执行的代码不断在第一次EF对象在之后试图连接到数据库在同一事务中已经进行了直接连接。

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

  1. ,你有没有Application Name=参数
  2. 自动生成一个后缀Application Name=EntityFrameworkMUF

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

相关问题