ADO实体框架是否支持非DTC事务?在一个EntityContext和一个TransactionScope中执行多个查询会导致DTC晋升。

3

我有一个使用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();
    }
}
4个回答

7

4
你没有提及,但听起来你正在使用SQL Server 2005。在SQL Server 2005下,如果在TransactionScope内打开多个连接,则事务将从轻量级事务升级为分布式事务。无论是同一数据库还是相同的ConnectionString,都会被升级。
这不是Entity Framework的“问题”,而更多是System.Transactions的现有行为。这个问题也存在于常规的ADO.NET中。过去我曾使用过Enterprise Library,在幕后维护了参与事务的连接列表,如果你在事务中尝试检索新连接,它将返回已经打开并参与你的事务的连接。
如果你使用SQL Server 2008,则改进了该行为,在打开到同一数据库的多个连接时不会升级事务

1
我们遇到了同样的问题,但在短期内升级不可行。因此,我们编写了代码来显式打开连接(StoreConnection)。这样可以避免事务升级。由于ObjectContext不会多次打开/关闭连接。 - Guillaume Schuermans

1

导致使用分布式事务的不是实体框架,而是 TransactionScope。EF 将使用“普通”事务来包装在单个调用 SaveChanges() 上下文中执行的所有 SQL 语句。在您提供的示例中,您只有一个对 SaveChanges 的调用。因此,您根本不需要使用 TransactionScope 来使您的更改以原子方式应用。

我不知道如何使 TransactionScope 使用非分布式事务,但我相信这不是实体框架在做这件事。


0
我在使用Entity Framework和ASP.NET成员系统时遇到了DTC升级问题,因为这两个系统使用不同的连接字符串。在成员系统的连接字符串中设置"Enlist=false"解决了我的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接