正如我们在第16章《概述插入、更新和删除数据》里探讨的那样,GridView控件内建的功能支持对每行数据的编辑和删除功能,你只需要稍稍动一下鼠标就可以创建丰富的数据修改界面而不用写一行代码.但是,在某些情况下,这还不够,我们需要让用户能够成批地处理数据.
比如,很多基于web(web-based)的电子邮件客户端,将所有邮件出来,每条邮件除了包含邮件信息(主题、发送者等)外,还包含一个checkbox控件。这些界面允许用户同时删除多个邮件,用户只需要选中邮件,再点"删除所选邮件"按钮.当用户要编辑多条不同的记录的时候,提供一个批编辑界面是比较理想的.我们用不着让用户每次都选中一条要编辑的记录,再做相关的修改,最后点“更新”按钮,在批编辑界面里每条记录都有各自的编辑选项,用户可以快速地编辑多条记录再点“Update All”按钮来保存对他们所做的修改.本系列我们将考察如何创建对数据进行添加、编辑、删除批处理的界面.
如果想对批处理执行atomic operation(原子操作), 那么首先,所做的操作要么都执行成功要么都失败,另外还要对数据访问层进行扩充以支持database transactions(数据库事务)。数据库事务确保INSERT, UPDATE, 和 DELETE语句执行的atomicity(原子数)置于数据库事务的保护之下.另外,绝大多数的当代数据库系统都支持数据库事务.
在本系列我们先看如何扩充数据访问层以支持数据库事务,接下来我们看如何创建页面以包含添加、更新、删除数据的批处理界面,让我们开始吧.
注意:在批处理事务里修改数据时,原子数(atomicity)并非总数必要的。在批处理的某些情况下,某些修改成功某些修改失败是可以接受的。比如删除电子邮件时,有些邮件在删除过程中发生了数据库错误,有些邮件没有发生错误,对这种没有发生错误的邮件,批处理照样将其删除掉.对这种情况,我们没有必要设置数据访问层DAL支持数据库事务.不过在其它某些情况下,原子数是至关重要的.比如某个客户想把资金从一个银行帐户转移到另一个银行帐号,下面2个操作必须执行成功:首先,将第一个帐号的资金扣除,然后将资金转入第二个帐号.如果第一步执行成功,第二步执行失败,银行当然高兴,客户怕是要发疯了.在后面的文章里我们将创建添加、更新、删除的批处理界面,就算你不打算在这些页面里使用数据库事务,我也希望你照着本篇文章,对数据访问层进行扩展一支持数据库事务.
事务概述
绝大多数的数据库都支持事务,它可以将多个数据库命令当成一个逻辑单位进行处理.这些包含事务的命令要么都执行成功要么都执行失败.
一般来说,事务通过SQL命令来执行,使用如下的模式:
1.声明事务开始
2.执行构成事务的那些SQL命令
3.如果在第二步中的任何一个命令出错,执行事务回滚(rollback the transaction)
4.如果在第二步中的所有命令成功执行,提交事务
这些SQL命令可以通过手写的方式输入,比如写SQL脚本、创建存储过程、也可以通过编程的方式来构建,比如使用ADO.NET技术或调用System.Transactions namespace命名空间的类.在本文,我们仅仅考察用ADO.NET技术管理事务.在后面的教程我们看如何在数据访问层Data Access Layer里使用存储过程,到那时,我们再来考察这些创建、回滚、提交事物的SQL命令。另外,要获得更多信息请参考文章《Managing Transactions in SQL Server Stored Procedures》()
注意:System.Transactions namespace命名空间的TransactionScope class类允许开发者通过编程的方式获取事务里的一系列命令,且允许事务包含多个数据源,甚至类型不同,比如:Microsoft SQL Server database, 或Oracle database,甚至Web service.本教程我们使用ADO.NET技术而非TransactionScope class类,是因为ADO.NET指定数据库事务更详细,且在很多情况下占用资源更少.此外,在某些情况下,TransactionScope class类要用到Microsoft Distributed Transaction Coordinator (MSDTC),围绕MSDTC的配置、执行和性能问题是比较专业、高级的问题稍微超出了本教程的范围.
在ADO.NET里,通过调用SqlConnection class类的BeginTransaction method方法启动事务, 该方法返回一个SqlTransaction object对象.将构成事务的数据操作命令放在try...catch区域,如果在try区域的某个命令出错的话,程序将转到catch区域,在此,通过SqlTransaction object对象的Rollback method方法执行事务回滚。如果所有的命令执行成功,将调用位于try区域底部的SqlTransaction object对象的Commit method方法来提交事务.下面的代码片段揭示了该模式。要想看在ADO.NET里使用事务的更多例子,请参阅文章《Maintaining Database Consistency with Transactions》().