本地事务 (ADO.NET)
更新:November 2007
如果要将多项任务绑定在一起,使其作为单个工作单元来执行,可以使用 ADO.NET 中的事务。例如,假设应用程序执行两项任务。首先使用订单信息更新表。然后更新包含库存信息的表,将已订购的商品记入借方。如果任何一项任务失败,两个更新均将回滚。
确定事务类型
事务如果是单阶段事务,并且由数据库直接处理,则属于本地事务。事务如果由事务监视程序进行协调并使用故障保护机制(例如两阶段提交)解决事务,则属于分布式事务。
每个 .NET Framework 数据提供程序使用自己的 Transaction 对象来执行本地事务。如果要求在 SQL Server 数据库中执行,请选择 System.Data.SqlClient 事务。对于 Oracle 事务,使用 System.Data.OracleClient 提供程序。此外,还提供了一个新的 DbTransaction 类,用于编写需要事务并且与提供程序无关的代码。
说明: |
---|
在服务器上执行时,事务最有效。如果使用的 SQL Server 数据库广泛使用显式事务,应考虑使用 Transact-SQL BEGIN TRANSACTION 语句以存储过程的形式编写这些事务。有关执行服务器端事务的更多信息,请参见“SQL Server 联机图书”。 |
使用单个连接执行事务
在 ADO.NET 中,使用 Connection 对象控制事务。可以使用 BeginTransaction 方法启动本地事务。开始事务后,可以使用 Command 对象的 Transaction 属性在该事务中登记一个命令。然后,可以根据事务组件的成功或失败,提交或回滚在数据源上进行的修改。
说明: |
---|
不应对本地事务使用 EnlistDistributedTransaction 方法。 |
事务的作用域限于该连接。以下示例执行显式事务,该事务由 try 块中两个独立的命令组成。这两个命令对 AdventureWorks SQL Server 2005 示例数据库的 Production.ScrapReason 表执行 INSERT 语句,如果没有引发异常,则提交。如果引发异常,catch 块中的代码将回滚事务。如果在事务完成之前事务中止或连接关闭,事务将自动回滚。
示例
按照下列步骤执行事务。
调用 SqlConnection 对象的 BeginTransaction 方法,以标记事务的开始。BeginTransaction 方法返回对事务的引用。此引用分配给在事务中登记的 SqlCommand 对象。
将 Transaction 对象分配给要执行的 SqlCommand 的 Transaction 属性。如果在具有活动事务的连接上执行命令,并且尚未将 Transaction 对象配给 Command 对象的 Transaction 属性,则会引发异常。
执行所需的命令。
调用 SqlTransaction 对象的 Commit 方法完成事务,或调用 Rollback 方法结束事务。如果在 Commit 或 Rollback 方法执行之前连接关闭或断开,事务将回滚。
以下代码示例演示对 Microsoft SQL Server 使用 ADO.NET 的事务逻辑。
Using connection As New SqlConnection(connectionString)
connection.Open()
' Start a local transaction.
Dim sqlTran As SqlTransaction = connection.BeginTransaction()
' Enlist a command in the current transaction.
Dim command As SqlCommand = connection.CreateCommand()
command.Transaction = sqlTran
Try
' Execute two separate commands.
command.CommandText = _
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')"
command.ExecuteNonQuery()
command.CommandText = _
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')"
command.ExecuteNonQuery()
' Commit the transaction
sqlTran.Commit()
Console.WriteLine("Both records were written to database.")
Catch ex As Exception
' Handle the exception if the transaction fails to commit.
Console.WriteLine(ex.Message)
Try
' Attempt to roll back the transaction.
sqlTran.Rollback()
Catch exRollback As Exception
' Throws an InvalidOperationException if the connection
' is closed or the transaction has already been rolled
' back on the server.
Console.WriteLine(exRollback.Message)
End Try
End Try
End Using
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// Start a local transaction.
SqlTransaction sqlTran = connection.BeginTransaction();
// Enlist a command in the current transaction.
SqlCommand command = connection.CreateCommand();
command.Transaction = sqlTran;
try
{
// Execute two separate commands.
command.CommandText =
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
command.ExecuteNonQuery();
command.CommandText =
"INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
command.ExecuteNonQuery();
// Commit the transaction.
sqlTran.Commit();
Console.WriteLine("Both records were written to database.");
}
catch (Exception ex)
{
// Handle the exception if the transaction fails to commit.
Console.WriteLine(ex.Message);
try
{
// Attempt to roll back the transaction.
sqlTran.Rollback();
}
catch (Exception exRollback)
{
// Throws an InvalidOperationException if the connection
// is closed or the transaction has already been rolled
// back on the server.
Console.WriteLine(exRollback.Message);
}
}
}
请参见
概念
SQL Server 的 System.Transactions 集成 (ADO.NET)