3

我有一个使用实体框架的 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

4 回答 4

7
  1. 在连接字符串上设置Enlist=false以避免在事务中自动登记。

  2. 手动将连接登记为事务范围的参与者。(http://msdn.microsoft.com/en-us/library/ms172153%28v=VS.80%29.aspx)

于 2010-08-04T17:44:02.087 回答
4

您没有提到,但听起来您使用的是 SQL Server 2005。在 SQL Server 2005 下,如果在 TransactionScope 内打开了多个连接,则事务将从 轻量级事务升级为分布式事务。如果它是同一个数据库和同一个 ConnectionString 并不重要——它仍然会被提升。

这不是 Entity Framework 的“问题”,而是 System.Transactions 的现有行为。常规 ADO.NET 也存在此问题。过去,我使用过 Enterprise Library,它在后台维护了一个参与事务的连接列表,如果您在事务中尝试检索新连接,它将返回已经打开并参与您的连接的连接交易。

如果您使用 SQL Server 2008,则行为会得到改进,以便在打开到同一数据库的多个连接时不会提升事务

于 2010-01-08T23:15:35.630 回答
1

导致使用分布式事务的不是实体框架;相反,它是TransactionScope。EF 将使用“正常”事务来包装在单个调用上下文中执行的所有 SQL 语句SaveChanges()。在您给出的示例中,您只有一次调用SaveChanges. 因此,您根本不需要使用TransactionScope原子来应用您的更改。

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

于 2010-01-08T13:00:00.040 回答
0

我在使用带有 ASP.NET 成员资格系统的实体框架时遇到了 DTC 升级问题,因为两者使用不同的连接字符串。在会员系统的连接字符串中设置“Enlist=false”为我解决了这个问题。

于 2012-09-27T12:04:27.280 回答