【发布时间】:2011-04-22 22:10:32
【问题描述】:
我想了解在 EntityFramework(w/Sql Server 2008)上使用 TransactionScopeOption.RequiresNew 的权衡/缺点是什么,我们为什么要这样做?不应该总是使用RequiresNew。
问候。
【问题讨论】:
标签: c# .net sql entity-framework
我想了解在 EntityFramework(w/Sql Server 2008)上使用 TransactionScopeOption.RequiresNew 的权衡/缺点是什么,我们为什么要这样做?不应该总是使用RequiresNew。
问候。
【问题讨论】:
标签: c# .net sql entity-framework
您应该使用Required 而不是RequiresNew。 RequiresNew 意味着每个操作都将使用一个新事务,即使已经存在一个包含的事务范围。这肯定会导致死锁。即使使用Required,TransactionScope 也存在另一个严重问题,即默认情况下它会创建一个Serializable 事务,这是一个非常糟糕的选择,并且是另一个通往死锁地狱且没有可扩展性的捷径。见using new TransactionScope() Considered Harmful。您应该始终使用显式的TransactionOption 将隔离级别设置为ReadCommitted 创建一个事务范围,这是一个更加合理的隔离级别:
using(TransactionScope scope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions {
IsolationLevel = IsolationLevel.ReadCommitted}))
{
/// do work here
...
scope.Complete();
}
【讨论】:
RequiresNew 在您想要独立事务时使用,而不是调用上下文事务的一部分。换句话说,从不。
RequiresNew 对日志记录或审计很有用,无论包含事务如何都应该成功。我同意,使用前请慎重考虑。
IEnlistmentNotification,否则它不会在外部事务失败时始终记录并且永远不会回滚吗?
RequiresNew 不应用于隔离日志记录/审计与可能中止事务,如果说日志记录代码抛出异常,这就是 TransactionScope.Suppress 明确设计的目的。
我只是想在这里补充一点,在某些情况下,我编写的方法位于父事务范围内,在这些情况下我不想依赖于 scope.Complete() 可能会或可能不会关闭父事务,所以我们需要设置 RequiresNew。
虽然我同意一般来说没有必要,但应该使用已提交的读取。
http://msdn.microsoft.com/en-us/library/ms172152(v=vs.90).aspx
【讨论】: