TransactionScope 事务 = new TransactionScope() VS TransactionScope s = context.Connection.BeginTransac

Posted

技术标签:

【中文标题】TransactionScope 事务 = new TransactionScope() VS TransactionScope s = context.Connection.BeginTransaction()【英文标题】:TransactionScope transaction = new TransactionScope() VS TransactionScope s = context.Connection.BeginTransaction() 【发布时间】:2020-04-24 21:45:55 【问题描述】:

我只想知道如果事务未完成,是否要回滚数据库中的所有更改,这两者有什么区别

 using (TransactionScope transaction = new TransactionScope())

using (var dbContextTransaction = context.Database.BeginTransaction())

读到这两个我很困惑:

Connection.BeginTransaction and Entity Framework 4?

https://docs.microsoft.com/en-us/ef/ef6/saving/transactions

**请注意,如果有必要,我会在我的项目中使用实体框架 4

【问题讨论】:

“全部重做”是什么意思?如果需要生成的密钥,为什么不能使用事务? ***.com/questions/542525/… 和 ***.com/questions/22382892/… @AminGolmahalle 非常感谢你 @AminGolmahalle 我认为您的评论是最好的答案,如果您将其发布为答案,我可以标记它。 @Sepehr Estaki 是的,我很高兴你的问题得到了解决。 【参考方案1】:

来自Programming Microsoft SQL Server 2012:

显式事务存在许多痛点。第一个困难在于要求用于在事务内部执行更新的每个SqlCommand 对象必须将其Transaction 属性设置为BeginTransaction 返回的SqlTransaction 对象。这意味着您必须小心将SqlTransaction 对象传递到代码中执行更新的任何位置,因为未能将其分配给事务中每个SqlCommand 对象的Transaction 属性会导致运行时例外。当您需要在多个执行更新的方法调用中跟踪 SqlTransaction 对象时,问题会更加复杂。当这些方法需要足够灵活才能工作时,无论是否涉及或需要事务,管理事情变得更加困难。

当使用我们稍后将介绍的任何其他技术时,问题会更严重,这些技术在原始对象上提供抽象层。例如,因为SqlDataAdapter 实际上包装了三个不同的SqlCommand 对象(用于插入、更新和删除),所以您必须深入了解数据适配器并挂钩到它的三个底层命令对象,以便您可以设置它们的Transaction特性。 (我们通常不建议您在应用程序中混合和匹配不同的数据访问 API,但如果您必须跨技术组合对更新进行事务化处理,隐式事务可以轻松实现。)

TransactionScope 对象在 2005 年作为 .NET 2.0 的专用事务管理 API 的一部分引入,可让您对事务进行隐式编码。这是一种出色的方法,可以使您摆脱与显式事务相关的所有上述负担。因此,这里的指导是尽可能始终使用隐式事务。当您允许框架为您处理事务管理时,您将编写更灵活的更少代码。但是,理解SqlTransaction 对象的显式事务仍然很重要,因为您可能需要集成和扩展已经使用显式事务的现有代码。因此,我们将涵盖这两种事务管理样式,让您为所有情况做好准备。

除了隐式事务之外,事务管理 API 还提供了更多好处。例如,当您的更新涉及跨多个数据库的更改时,TransactionScope 能够自动将轻量级事务(与单个数据库关联的事务)提升为分布式事务。

【讨论】:

【参考方案2】:

数据库。 BeginTransaction() 仅用于数据库相关操作事务,System.交易。 ... TransactionScope 用于在事务中混合数据库操作和 C# 代码。

请参阅下面的链接。希望它们对您有所帮助:

TransactionScope vs Transaction in LINQ to SQL

Database.BeginTransaction vs Transactions.TransactionScope

【讨论】:

【参考方案3】:

您应该注意 TransactionScope 的两个陷阱。

首先,默认情况下,它将创建一个具有 SERIALIZABLE 隔离级别的事务,这对于 SQL Server 来说是一个糟糕的选择。所以你应该总是像这样创建你的 TransactionScope:

public class TransactionUtils 

  public static TransactionScope CreateTransactionScope()
  
    var transactionOptions = new TransactionOptions();
    transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
    transactionOptions.Timeout = TransactionManager.MaximumTimeout;
    return new TransactionScope(TransactionScopeOption.Required, transactionOptions);
  

在这里查看咆哮:using new TransactionScope() Considered Harmful

第二个是TransactionScope支持分布式事务。因此,它将使您能够在单个事务中加入 不同的 连接,甚至是不同的资源提供者。虽然这偶尔有用,但更多时候是一个陷阱。如果您意外最终得到一个分布式事务,您可以意外依赖于在您的环境中拥有一个分布式事务协调器。因此,您应该采取措施避免出现分布式事务,例如在您的开发环境中关闭 Microsoft 分布式事务协调器 (MSDTC)。并确保任何时候您在事务中登记了多个方法,它们不会同时打开 SqlConnection。

【讨论】:

我怎样才能看到默认的隔离级别是SERIALIZABLE? 记录在这里:docs.microsoft.com/en-us/dotnet/api/…

以上是关于TransactionScope 事务 = new TransactionScope() VS TransactionScope s = context.Connection.BeginTransac的主要内容,如果未能解决你的问题,请参考以下文章

在啥情况下 SqlConnection 会自动加入环境 TransactionScope 事务?

C#分布式事务解决方案-TransactionScope

TransactionScope:避免分布式事务

TransactionScope事务

内存中的 Sqlite - TransactionScope - 已检测到环境事务

使用TransactionScope做分布式事务协调