【问题标题】:Can LINQ BeginTransaction works with new Context?LINQ BeginTransaction 可以与新的上下文一起使用吗?
【发布时间】:2015-06-04 04:00:35
【问题描述】:

我的项目是用Ninject开发的,比如我写了2个函数来插入或更新到数据库

public class PersonRepository : IPersonRepository {

    private readonly DbContext _context;

    public PersonRepository(DbContext context) {
        _context = context;
}

    public void InsertToDB(Person obj) {
        _context.Persons.Add(obj);
        _context.SaveChanges();
}   

    public void UpdateToDB(Person obj) {
        _context.Persons.Attach(obj);
        _context.SaveChanges();
    }   
}

在 Controller 中,我声明了相同的 DbContext 并使用事务:

public class PersonController : Controller {

    private readonly DbContext _context;
    private readonly IPersonRepository _repository;

    public PersonController(DbContext context, IPersonRepository repository) {
        _context = context;
        _repository = repository;
    }

    public ActionResult Index() {
        return View();
    }

    [HttpPost]
    public ActionResult ExecuteToDb(Person person1, Person person2) {
        using (var transaction = _context.Database.BeginTransaction(IsolationLevel.ReadCommitted)) {
            try {
                _repository.InsertToDB(person1);
                _repository.UpdateToDB(person2);

                transaction.Commit();
            } catch (Exception) {
                transaction.RollBack();
            }
        }
    }
}

那么如果InsertToDB()UpdateToDB()抛出任何异常,事务可以回滚吗?

我很担心,因为我觉得Controller和Repository的_context不一样,我现在无法测试,帮帮我,谢谢!

【问题讨论】:

  • SaveChanges 提交,因此如果抛出异常,更改将不会持续。不是吗?
  • @JNF 是的,如果抛出异常,我希望所有操作回滚:)
  • 我的意思是,据我所知,您的代码已经做到了

标签: c# linq entity-framework transactions


【解决方案1】:

这里有三个选项。首先,您可以将 Ninject 配置为对您的 PersonController 和您的 PersonRepository 使用相同的 DbContext 实例。为此,您可以将绑定配置为使用 InRequestScope()。然后,您可以调用 BeginTransaction,它是相同的上下文。

或者,您可以将 BeginTransaction、CommitTransaction 和 RollBackTrasaction 方法添加到我们的 IRepository 类中,并在您的存储库中实现这些方法。

第三种选择是只创建一个新的 TransactionScope() 而不是在上下文中调用 BeginTransaction。

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, 
       new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted, 
                                Timeout = TransactionManager.MaximumTimeout }))
{
    _repository.InsertToDB(person1);
    _repository.UpdateToDB(person2);

    // if exception occurs, Complete will not get called, so transaction
    // is automatically rolled back when Dispose is called when using()
    // goes out of scope.  If Complete is called, then Commit is called.
    scope.Complete();
}

【讨论】:

  • 谢谢,我用过TransactionScope,但是连接有些问题,而且TransactionScope没有Commit()Rollback(),只有Complete()。按照您的指南,我添加到我的 NinjectWebCommon.cs 以实例化相同的 DbContext:kernel.Bind<DbContext>().ToSelf().InRequestScope();。这是真的吗?
  • @KenPlus - 抱歉,您不需要调用 Rollback 或 Commit,您只需要 Complete。如果生成异常,则会自动发生回滚,因为没有调用 Complete。但是,是的,您对 InRequestScope 所做的工作有效
猜你喜欢
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 2022-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
相关资源
最近更新 更多