请参阅下面的代码。如果我初始化多个实体上下文,那么我在第二组代码上得到以下异常。如果我注释掉第二组它就可以了。
{“基础提供商在开放时失败。”}
内部:{“与底层事务管理器的通信失败。”}
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();
}
答案 0 :(得分: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();
}
答案 1 :(得分:19)
由于某种原因,您的MS-DTC(分布式事务协调员)无法正常工作。 MS-DTC用于协调跨多个异构资源的事务结果,包括多个sql连接。
请查看this link了解有关正在发生的事情的更多信息。
基本上,如果您确保MS-DTC正在运行并且正常工作,那么使用2个ADO.NET连接应该没有问题 - 无论它们是实体框架连接还是任何其他类型。
答案 2 :(得分:5)
将C:\ Windows \ msdtc.exe添加到防火墙和服务器上的防火墙例外。在我这样做之前,我花了很多年的时间来打开特定的端口号和范围无济于事。
答案 3 :(得分:4)
我要坚持这一点,因为我昨天和同事一起花了3个小时来调试这个问题。围绕此问题的每一个答案都表明这始终是防火墙问题;但在我们的情况下,它不是。希望这会让别人感到痛苦。
我们的情况是我们目前正在迁移到实体框架。这意味着我们有部分代码,其中单个事务连接内部使用new SqlConnection(connectionString).Open()
直接打开,并通过使用EF数据上下文间接打开。
这在我们的应用程序中已经运行了一段时间,但是当我们开始回顾性地围绕在生产中工作的代码进行测试时,从测试运行器执行的代码在第一次EF对象时不断抛出此错误尝试连接到数据库 在同一事务中建立直接连接后。
错误的原因最终证明,如果您没有为连接字符串提供Application Name=
参数,则实体框架默认添加一个(类似EntityFrameworkMUF
)。这意味着您的连接池中有两个不同的连接:
Application Name=
参数Application Name=EntityFrameworkMUF
并且无法在单个事务中打开两个不同的连接。生产代码指定了应用程序名称;因此它有效;测试代码没有。指定Application Name=
参数为我们修复了错误。
答案 4 :(得分:3)
顺便说一下,当您使用像这样的显式事务时,您应该考虑将SaveChanges(false)与AcceptChanges()结合使用。
这样,如果在SaveChanges(false)中出现问题,ObjectContext就不会丢弃您的更改,因此您可以稍后重新应用或执行一些错误记录等。
有关详情,请参阅此帖子:http://blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx
干杯
亚历
答案 5 :(得分:1)
问题是2个不同的DataContext有效地创建了两个不同的连接。
在这种情况下,事务HAS将被提升为分布式事务。我假设您的问题来自服务器和/或客户端上的MS DTC(Microsoft分布式事务处理协调器)的配置。 例如,如果服务器未配置为允许MSDTC的远程连接,则会遇到这种异常。
例如,您可以参考this MS page来解决MSDTC问题,并且谷歌填充了文章/论坛有关它的问题。
现在,它可能是其他东西,但它听起来确实是MSDTC问题。
答案 6 :(得分:0)
答案 7 :(得分:0)
在从MQ队列读取消息,处理它们并存储在SQL 2005 Express Edition数据库中时,我确实发生了类似的错误。我没有足够的时间去调查,直到2005年或者激动的Express版本是否导致了这个问题,但是切换到2008 Standard已经消除了这种特殊的行为。