我的项目是使用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并使用transaction:
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()
抛出任何异常,事务可以回滚吗?
我担心它,因为我认为控制器和存储库的_context是不同的,我现在无法测试它,帮助我,谢谢!
这里有三个选项。首先,你可以配置Ninject为你的PersonController和PersonRepository使用相同的DbContext实例。您可以通过配置绑定来使用InRequestScope()来实现这一点。然后,你可以调用BeginTransaction,它是相同的上下文。
或者,你可以在IRepository类中添加BeginTransaction, CommitTransaction和rollbacktransaction方法,并在你的Repository中实现它们。
第三个选择是只创建一个新的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();
}