LINQ to SQL中的经典事务模式之间有什么区别:
using(var context = Domain.Instance.GetContext())
{
try
{
context.Connection.Open();
context.Transaction = context.Connection.BeginTransaction();
/*code*/
context.Transaction.Commit();
}
catch
{
context.Transaction.Rollback();
}
}
vs TransactionScope对象
using (var context = Domain.Instance.GetContext())
using (var scope = new TransactionScope())
{
try
{
/*code*/
scope.Complete();
}
catch
{
}
}
答案 0 :(得分:74)
应该注意的是,使用TransactionScope
时,您不需要try/catch
构造。您只需在作用域上调用Complete
,以便在退出作用域时提交事务。
话虽如此,TransactionScope
通常是一个更好的选择,因为它允许您将调用嵌套到可能需要事务的其他方法,而无需传递事务状态。
在BeginTransaction
对象上调用DbConnection
时,如果要在同一事务中执行其他操作,则必须传递该事务对象,但是使用不同的方法。
使用TransactionScope
,只要范围存在,它就会处理在线程上注册当前Transaction
的所有内容,从而使代码更清晰,更易于维护。
除此之外,您还可以使用其他可以参与事务的资源,而不仅仅是与数据库的连接。
应该注意的是,在需要充分利用连接和数据库操作的情况下,您可能不想使用TransactionScope
;即使对于单个数据库,您也可以使用分布式事务处理协调器,并将事务转换为分布式事务(即使对于单个数据库连接)。
在这些情况下,在弄乱您的设计时,您可能需要考虑传递特定于连接的事务。
或,如果您知道将一致地使用一个资源(并且在同一个线程上),您可能想要创建一个引用计数连接/事务的类。
您将创建一个在构造时创建资源/增加计数的类。它还将实现IDisposable
(当计数为零时,您将减少/释放/提交/中止),并将计数存储在已应用ThreadStaticAttribute
的变量中。
这允许您将事务管理与逻辑代码分开,并且仍然可以相当有效地保留单个资源(而不是升级到分布式事务)。
答案 1 :(得分:34)
Linq2SQL将使用隐式事务。如果您的所有更新都在一次提交中完成,则您可能不需要自己处理该事务。
从文档(强调我的):
当您调用SubmitChanges时,LINQ to SQL会检查调用是否在Transaction的范围内,或者Transaction属性(IDbTransaction)是否设置为用户启动的本地事务。 如果找不到任何事务,LINQ to SQL将启动本地事务(IDbTransaction)并使用它来执行生成的SQL命令。当所有SQL命令都成功完成后,LINQ to SQL将提交本地事务和回报。
答案 2 :(得分:21)
一个很大的区别(经验教训) - TransactionScope使用MS DTC进行事务管理。
如果您的应用程序必须仅管理数据库事务,并且不涉及任何服务或远程调用,则可以使用数据库本机事务(DbTransactions)跳过与MS DTC相关的潜在问题。
答案 3 :(得分:6)
TransactionScope为所有资源管理器(SQL服务器,活动目录,文件系统......)提供统一管理。此外,人们可以编写自己的资源管理器:检测事务范围的代码,加入它并完全像SQL服务器那样工作:像事务的其他参与者一样提交或恢复更改。我相信TransactionScope是主流并忘记了MS SQL本机事务,直到失败进入巨大的陷阱: Windows Server 2008 WEB Edition附带受限制的分布式事务处理协调器服务,而事务范围仅适用于单台计算机。 如果IIS和SQL Server安装在不同的计算机上,则ASP.NET应用程序将在此系统上失败。考虑到大多数公共域提供商提供Windows Server WEB版和SQL服务器都在不同的服务器上。这意味着,您必须使用显式事务管理来处理本机事务...
答案 4 :(得分:4)
我认为它们基本上与TransactionScope类将与ADO.NET底层连接接口以创建并提交或回滚事务相同。刚刚创建了TransactionScope类,以便使用ADO.NET持久性清理器。
编辑:澄清关于casperOne's addition的声明,它将创建事务的TransactionScope,然后连接将查看TransactionScope创建的事务并使用它,因为它是可用的。