我有一个使用Entity Framework的Web应用程序 - 我们使用TransactionScope类来提供环境事务。
有没有办法告诉EF使用标准T-SQL交易优先于DTC交易?我们经常对一个EntityContext和一个TransactionScope实例中的不同表进行大量查询,但这似乎总是将事务提升为DTC
我举了一个简短的例子,见下文。对单个表的查询正确地启动了T-SQL事务,并且在连接SPID 54上 然后对ContactUs表进行查询,并且EF在不同的连接(SPID 53)上执行此操作,该连接具有将事务提升为DTC事务的效果。**
using (MyEntities DB = new MyEntities())
{
using (TransactionScope t = new TransactionScope())
{
DB.Individual.First().EmailAddress = "bob" + DateTime.Now.Second.ToString() + "@bob.com"; // done on connection 54
DB.ContactUs.First(); // done on connection 53 thus promoting the transaction!!
DB.SaveChanges();
t.Complete();
}
}
答案 0 :(得分:7)
在连接字符串上设置 Enlist = false ,以避免在事务中自动登记。
手动登记连接作为事务范围的参与者。 (http://msdn.microsoft.com/en-us/library/ms172153%28v=VS.80%29.aspx)
答案 1 :(得分:4)
您没有提及,但听起来您正在使用SQL Server 2005.在SQL Server 2005下,如果在TransactionScope中打开了多个连接,则事务将escalate from a lightweight transaction to a distributed transaction。如果它是相同的数据库和相同的ConnectionString并不重要 - 它仍然会被提升。
这不是Entity Framework的“问题”,因为它是System.Transactions的现有行为。普通的ADO.NET也存在这个问题。在过去,我使用了Enterprise Library,其中包含了参与事务的连接列表,如果您在事务中尝试检索新连接,它将返回已经打开并参与您的连接的连接。事务。
如果您使用SQL Server 2008,则行为会得到改进,以便transactions are not promoted when opening multiple connections to the same database。
答案 2 :(得分:1)
导致使用分布式交易的不是实体框架;相反,它是TransactionScope
。 EF将使用“正常”事务来包装在对SaveChanges()
的单个调用的上下文中执行的所有SQL语句。在您给出的示例中,您只需拨打一次SaveChanges
。因此,您根本不需要使用TransactionScope
来自动应用更改。
我不知道如何使TransactionScope
使用非分布式事务,但我有理由相信它不是实体框架。
答案 3 :(得分:0)
我正在使用带有ASP.NET成员资格系统的Entity Framework来解决DTC升级问题,因为两者使用不同的连接字符串。在会员系统的连接字符串中设置“Enlist = false”为我解决了问题。