【问题标题】:TransactionScope in .NET application.NET 应用程序中的 TransactionScope
【发布时间】:2009-08-31 11:24:06
【问题描述】:
我已经编写了一个代码块来在 SQL Server 数据库中进行数据库事务。如果执行期间出现任何故障,我正在使用 TransactionScope 类回滚所有更改。
如果我在运行 SQL SERVER 的系统中运行应用程序,我没有问题。
如果我在一个系统中运行应用程序并且 SQL SERVER 在另一个系统中运行,我会收到一个错误,即 MSDTC 已禁用。
如果我在 DBServer 运行系统中启用 MSDTC,我的应用程序工作正常。
如果我必须使用 ORACLE db,系统将如何工作?我应该在 ORACLE DB 服务器上配置一些东西来启用事务范围吗?请帮帮我。
谢谢,
P.Gopalakrishnan。
【问题讨论】:
标签:
.net
scope
transactions
【解决方案1】:
TransactionScope 虽然在概念上很简单,但在幕后隐藏了很多魔法。它使您能够使用分布在多台机器上的一个事务。为此,它需要来自数据库的复杂支持——而且开销可能很高,也可能不高。
一个更简单、更有限的技术对你来说可能就足够了:DbTransaction。您的 Db 提供者可以实现语义类似于 sql 的 BEGIN TRANSACTION 和 COMMIT TRANSACTION 的事务:简而言之,一个仅跨越单个机器上的单个连接的事务。
您的代码将类似于...
DbCommand cmd = ...;
using (DbTransaction trans = Connection.BeginTransaction()) {
cmd.Transaction = trans; //sometimes optional, though MS-SQL requires it.
cmd.ExecuteNonQuery()
[...other db commands with the same connection and transaction...]
trans.Commit();
}
明确地说:您可以在事务打开时使用其他几个连接 - 但它们之间没有链接。在不同连接上执行的命令不会在事务中止时回滚(很像任意 C# 代码不会在事务中止时回滚)。
这种方法重量更轻,粒度更细,适用于更广泛的数据库提供程序,并且不需要启动 MSDTC。另一方面,事务是特定于连接的(如果您有多个连接,它们不共享事务),它们不能被分发,并且您需要手动将命令登记到事务中(至少对于 MS -SQL)。
注意,如果您未能在事务中登记命令,MS-SQL 将抛出异常,SQLite 仍会隐式登记命令,我不确定 oracle 是做什么的。由于无论如何必须在事务中注册所有命令,这只是一个笨拙的冗余 API,但问题不大。
【解决方案2】:
TransactionScope 支持(混合)快速本地事务,并可以在需要时将它们提升为更昂贵的分布式事务。对于分布式事务,需要 MSDTC。
提升到分布式事务的一个原因是如果您在同一个 TransactionScope 中涉及第二个数据库。
Oracle Data Provider 10.2.0.3 及更高版本支持本地事务 + 分布式事务(与 SQL Server 2005 及更高版本相同)。旧版本的 ODP.NET 仅支持分布式事务。