使用事务机制
事务是单独的工作单元。如果事务成功,在事务中所做的所有的数据修改都会在提交时完成并且永久地成为数据库的一部分。如果事务遇到错误,则必须取消或回滚,这样所有的数据修改都将被清除。
可以在ADO.NET中使用事务,以便确保数据库的一致性和完整性。
完成本节学习,你将能够:
了解事务的重要性
启动一个事务
为事务指定适当的隔离级别
提交或回滚事务
3.6.1 事务
事务是一组相关的任务,这些任务作为一个单元要么一起成功要么一起失败。用事务处理的术语来说,事务要么提交要么回滚。对于一个要提交的事务,所有的组成部分都必须保证对数据的任何更改都是永久性的。不论系统崩溃或是发生其它无法预料的事件,更改都必须是永久性的。
只要有一个部分不能达到此要求,整个事务就会失败。事务范围内所有对数据的改变都会回滚到某个特定的设置点。
对于使用事务的例子,考虑下面的情形:一个ASP.NET页面执行两个任务。首先,在数据库中创建了一个新表。然后,调用特定对象来收集数据、格式化数据以及向新表中插入数据。这两个任务是相关甚至是相互依赖的,在这种情形中,除非能向新表中填充数据,否则就要避免创建新表。在一个事务范围内执行两个任务会强制两者之间的联系。如果第二个任务失败,则第一个任务就会回滚到创建新表前的某个点。
(1) 本地事务和分布式事务
可以创建本地事务或分布式事务,描述如下:
本地事务
本地事务被限制在某种单独的数据资源内,例如数据库或消息队列。这些数据资源通常提供本地事务功能。由于这些事务由数据资源本身来控制,所以管理起来轻松高效。
分布式事务
事务还可以跨越多种数据资源。分布式事务使您可以去协调不同系统上特有的操作,从而使它们一起成功或者一起失败。
(2) ACID属性
术语ACID是指事务在应用程序中所起的作用。由事务处理的先驱们所创立的”ACID”,代表了原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持续性(Durability)。
这些属性确保可预知行为,强调了事务的“所有或没有”(all-or-none)的宗旨的作用;此宗旨的目的是在可变因素很多时能减少管理负担。
原子性
事务是一个工作单元。在应用程序中,一系列包含在 BEGIN TRANSACTION 和 END TRANSACTION 语句之间的操作将在该工作单元中进行。事务只执行一次,且是不可分的,即要么完成全部工作要么不做任何工作。
一致性
事务是一个完整的单元,因为它保持数据的一致性,它可以将数据从某种一致性状态转换到另一种一致性状态。
一致性需要能够保持被事务所绑定的数据。某些维护一致性的责任由应用程序开发人员承担,他们必须确保应用程序强制了所有已知的完整性约束。
隔离性
事务是一个独立的单元。每个并行执行的事务看起来都应该像是系统中惟一的一个事务。
隔离性要求即使所有事务都在同时运行,每个事务也都应该像是惟一存在的一个事务那样去操作数据存储区。事务永远也看不到其他事务的中间阶段。
持续性
如果事务成功,那么即使在提交后计算机立即崩溃,系统仍将保证对该事务的更新。专用的日志可以让系统重新启动程序来完成未完成的操作,以使事务可持续。
3.6.2 使用SQL语句管理事务
使用SQL语句可以在数据层管理事务。
(1) SQL事务语句
表 3 8描述了一些用于管理事务的SQL语句。可以在存储过程中使用这些语句,控制数据层中的事务行为。
表 3 8
事务语句 描述
BEGIN TRANS 标记事务的开始。所有在BEGIN TRANS语句后执行的语句被视为事务的一部分。
COMMIT TRANS 标记一个成功事务的结束,提交从BEGIN TRANS语句以后所做的所有更改。
ROLLBACK TRANS 将事务回滚到该事务的开始处。
示例
下面的示例描述了如何使用Transact-SQL管理事务。本例删除了某个指定产品定单的详细信息,然后删除了产品本身。如果产生任何错误,为了保证一致性会回滚整个事务。
BEGIN TRANS
DECLARE @orderDetailsError int, @productError int
DELETE FROM "Order Details" WHERE ProductID=42
SELECT @orderDetailsError = @@ERROR
DELETE FROM Products WHERE ProductID=42
SELECT @productError = @@ERROR
IF @orderDetailsError = 0 AND @productError = 0
COMMIT TRANS
ELSE
ROLLBACK TRANS
3.6.3 使用ADO.NET管理事务
ADO.NET能够在中间层的.NET Framework应用程序中管理事务。可以选择在数据层中执行事务。
SqlConnection和 OleDbConnection对象包含一个BeginTransaction方法,它能够返回SqlTransaction 或OleDbTransaction对象。事务对象拥有Commit 和Rollback方法来管理应用程序中的事务。
(1) 执行事务
通过使用ADO.NET执行事务
1) 调用连接对象的BeginTransaction 方法。将返回值赋给一个SqlTransaction(或OleDbTransaction)类型的变量。
2) 为要在事务中执行的所有命令对象设置Transaction属性来引用事务对象。
3) 执行必要的命令对象。
4) 如果命令圆满完成,则调用事务对象的Commit方法。如果发生任何问题,则调用Rollback回滚到初始条件。
示例
下面的示例使用事务来协调Northwind数据库中的多个DELETE语句。第一个DELETE语句删除了”Order Details”表中ProductID 为42的所有条目,第二个DELETE语句删除了Products表中的ProductID 为42的产品。如果发生任何错误,事务将回滚并且所有删除操作都被取消。
' 打开数据库连接,开始一个事务。
' 在事务中执行两个删除语句。
' 适当地提交或回滚事务。
cnNorthwind.Open()
Dim trans As SqlTransaction = cnNorthwind.BeginTransaction()
Dim cmDel As New SqlCommand()
cmDel.Connection = cnNorthwind
cmDel.Transaction = trans
Try
cmDel.CommandText = _
"DELETE [Order Details] WHERE ProductID = 42"
cmDel.ExecuteNonQuery()
cmDel.CommandText = "DELETE Products WHERE ProductID = 42"
cmDel.ExecuteNonQuery()
trans.Commit()
Catch Xcp As Exception
trans.Rollback()
Finally
cnNorthwind.Close()
End Try