为什么TransactionScope不能与实体框架一起使用?
请参阅下面的代码。如果我初始化多个实体上下文,那么我在第二组代码上得到以下例外。如果我注释掉第二组,它就可以工作。为什么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();
}
您的MS-DTC(分布式事务协调器)出于某种原因无法正常工作。 MS-DTC用于协调跨多种异构资源(包括多个sql连接)的事务结果。
查看this link以了解正在发生的更多信息。
基本上,如果你确定你的MS-DTC正在运行并正常工作,你应该没有使用2个ADO.NET连接的问题 - 无论它们是实体框架连接还是任何其他类型。
可避免管理自己的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();
}
的问题是,2种不同的DataContext有效地创建两个不同的连接。
在这种情况下,事务HAS被提升为分布式事务。我假设你的问题来自服务器和客户端上MS DTC(Microsoft分布式事务处理协调器)的配置。 例如,如果服务器未配置为允许MSDTC的远程连接,则会遇到此类异常。
例如,您可以参考this MS page来排除MSDTC问题,并且Google会向文章/论坛提问。
现在,它可能是别的,但它听起来像是一个MSDTC问题。
BTW你应该考虑结合使用的SaveChanges(假)用的AcceptChanges在使用你喜欢这个明确的交易()。如果
这样东西的SaveChanges(假)失败,则ObjectContext的还没有放弃你的更改,以便以后可以重新申请或者做一些错误记录等
看到这个职位的详细资料:http://blogs.msdn.com/alexj/archive/2009/01/11/savechanges-false.aspx
干杯
亚历
添加C:\ WINDOWS \ msdtc.exe到防火墙和服务器上的防火墙例外。我花了很多时间在开放特定的端口号码和范围之前瞎搞,在我这样做之前无济于事。
从MQ队列中读取消息,处理它们并存储在SQL 2005 Express Edition数据库中时,使用DTC时发生过类似的错误。我没有足够的时间来调查2005年底或者令人兴奋的Express版造成这个问题,但切换到2008年Standard将这种特殊行为淡化了出来。
我打算在这里坚持下去,因为昨天我和同事一起花了3个小时来调试这个问题。围绕这个问题的每一个答案都表明,这总是一个防火墙问题。但在我们的情况下,它不是。希望这会使其他人免于痛苦。
我们的情况是,我们目前正在迁移到实体框架。这意味着我们有部分代码在单个事务连接内部直接使用new SqlConnection(connectionString).Open()
打开,并通过使用EF数据上下文间接打开。
这在我们的应用程序中一直运行良好,但是当我们开始回溯并将测试放在生产中的代码周围时,从测试运行器执行的代码不断在第一次EF对象在之后试图连接到数据库在同一事务中已经进行了直接连接。
错误的原因最终证明是,如果您没有为连接字符串提供参数Application Name=
,实体框架会默认添加一个参数(如EntityFrameworkMUF
)。这意味着你必须在你的连接池两个不同的连接方式:
- ,你有没有
Application Name=
参数 - 自动生成一个后缀
Application Name=EntityFrameworkMUF
,这是不可能的手动打开一个在单个事务中打开两个不同的连接。生产代码指定了一个应用程序名称;因此它工作;测试代码没有。指定Application Name=
参数为我们修复了这个错误。
我不只是使用实体框架,因此重复使用EntityConnection也不是一个简单的解决方案(请参阅上面的编辑) – NotDan 2009-04-27 19:01:07
+1用于避免DTC。这并不是坏事,只是分布式交易不是轻易选择的东西。这是应用程序和资源的紧密链接,可能会降低设计的可用性。 – 2009-04-27 19:48:43
您也可以调用context.Connection.Open()手动管理它。你不需要手动创建EntityConnection – 2009-12-24 16:41:23