我正在寻找一种在TransactionScope存在的情况下执行查询并忽略TransactionScope的方法 - 基本上,我想无论如何都执行此特定查询。
我正在使用EF Code-First,并且应用程序的设计方式是,在单个调用期间多次打开新数据上下文,每个上下文都有自己的更改,并且所有这些更改都包含在单个TransactionScope中,该作用域在结尾处调用Complete()
,假设没有失败。在上下文内部,我们已覆盖了SaveChanges
,以便如果base.SaveChanges()
发生任何异常,我们可以在回滚事务之前将其捕获并记录到数据库中。
由于SaveChanges
发生在事务内部,因此显然不会发生记录,因为它属于与原始调用相同的事务。我试图完全忽略TransactionScope,仅用于记录代码。
这是一些简化的代码:
// From the context
public override int SaveChanges() {
try {
return base.SaveChanges();
} catch (Exception ex) {
// Writes to the log table - I want this to run no matter what
LogRepo.Log(/*stuff to log from the context*/);
throw;
}
}
// Inside the business logic
public void DoSomething() {
try {
using (var scope = new TransactionScope()) {
using (var context = new FooContext()) {
// Do something
context.SaveChanges();
}
using (var context = new FooContext()) {
// Do something else
context.SaveChanges();
}
scope.Complete();
}
} catch (Exception ex) {
// scope.Complete is never called, so the transaction is rolled back
}
}
我尝试使用普通的 ADO.NET 替代 EF 进行日志记录,但结果仍然相同 - 它也被回滚了。
我需要在 SaveChanges
内部进行错误处理,因为我记录的是正在保存的实体的状态 - 所以我不能轻松地将记录移动到其他地方。我可以在 SaveChanges catch
中构建消息,并将其抛出并让 DoSomething catch
记录它,但有数十个 DoSomething
方法,我更愿意只在一个地方处理这个问题。