如何使用Entity Framework进行交易?

pup*_*eno 27 entity-framework transactions

当你有这样的代码:

Something something = new Something();
BlahEntities b = new BlahEntities()    
b.AddToSomethingSet(something);
b.SaveChanges();
Run Code Online (Sandbox Code Playgroud)

如何在交易中运行该添加?

Kim*_*jor 55

ObjectContext具有可用于管理事务的连接属性.

using (var context = new BlahEntities())
using (var tx = context.BeginTransaction())
{
    // do db stuff here...
    tx.Commit();
}
Run Code Online (Sandbox Code Playgroud)

在异常情况下,事务将被回滚.因为对BeginTransaction()的调用需要和打开连接,所以在扩展方法中包含对BeginTransaction的调用是有意义的.

public static DbTransaction BeginTransaction(this ObjectContext context)
{
    if (context.Connection.State != ConnectionState.Open)
    {
        context.Connection.Open();
    }
    return context.Connection.BeginTransaction();
}
Run Code Online (Sandbox Code Playgroud)

我相信这种方法可能比TransactionScope有用的一种情况是,当您必须访问两个数据源并且只需要对其中一个连接进行事务控制时.我认为在这种情况下,TransactionScope将推广到可能不需要的分布式事务.

  • 这是迄今为止我的首选答案,因为TransactionScope是一个纯粹的乌托邦,并没有得到广泛实施.@Baig,context.Connection.BeginTransaction()永远不会升级到分布式事务(MSDTC). (6认同)
  • 这在EF4.1中不再有效.你必须调用`context.Connection.BeginTransaction`. (3认同)

Shi*_*iji 26

您可以将代码放在事务范围内

using(TransactionScope scope = new TransactionScope())
{
    // Your code
    scope.Complete(); //  To commit.
}
Run Code Online (Sandbox Code Playgroud)

TransactionScope位于System.Transactions命名空间中,该命名空间位于同名程序集中(您可能需要手动将其添加到项目中).

  • 使用TransactionScope时要小心.它引入了对MS DTC的依赖性,这是一个很难配置并带来高昂的性能价格.在TransactionScope中有多个事务后,它将启动分布式事务.它将不再只是在使用过的提供程序上运行的普通DbTransaction.此外,如果您使用的是Sql Server以外的数据库提供程序,则很可能它不支持分布式事务... (14认同)
  • 即使您查询同一数据库,也会将本地事务提升为分布式事务.如果您使用的是SQL Server 2005(或更高版本),它将在升级之前使用轻量级事务.如果您使用不支持升级的提供程序,即使在作用域内只执行一个查询,也会支付性能损失. (2认同)

Cyl*_*Cat 9

我知道对于LINQ to SQL,如果没有现有的环境事务(TransactionScope是"环境"事务),数据上下文将为SubmitChanges()创建一个事务.我还没有看到LINQ to Entities的文档记录,但我已经看到行为表明它对于Entity Framework也是如此.

因此,只要您使用一个SubmitChanges()(L2SQL)或SaveChanges()(Linq to Entities)进行所有相关更改,您就可以在不使用TransactionScope的情况下使用.您何时需要TransactionScope

  1. 使用多个SubmitChanges/SaveChanges为一个事务保存多个更改.
  2. 在一个事务中更新多个数据源(例如,Linq和ASP.NET成员资格SQL提供程序).
  3. 调用可能进行自己更新的其他方法.

我在使用嵌套的TransactionScopes时遇到了麻烦.他们应该工作,简单的测试用例可以工作,但是当我进入生产代码时,"内部"事务似乎与外部事务是同一个对象.症状包括"事务已提交,您不能再使用此事务"或"此事务对象已被处置"的错误.内部事务完成其工作后,外部事务中会发生错误.