简介
正如我们在数据插入、更新和删除概述 教程中探讨的那样,GridView 提供内置功能支持行级编辑和删除功能。您只需单击几次鼠标就可以创建丰富的数据修改界面而不用写一行代码,前提是您进行的编辑和删除是基于每行数据的。然而,在某些情况下,这还不够,我们需要让用户能够编辑或删除批量记录。
例如,大多数基于 web 的电子邮件客户端都使用一个网格列出每条消息,除了包含邮件的信息(主题、发送者等等)外,还包括一个复选框。该界面允许用户删除多个消息,方法是先勾选上它们,再单击“Delete Selected Messages ”按钮。在用户通常编辑多条不同记录的情况下,一个批量编辑界面则是一项理想的选择。用不着让用户对每条要修改的记录,单击Edit ,进行修改,然后单击 Update ,批量编辑界面里每条记录都有其各自的编辑界面。用户可以快速地修改需要更改的那几行,然后单击“Update All” 按钮保存这些更改。在本系列教程中,我们将探讨如何创建插入、编辑和删除批量数据的界面。
执行批操作时,重要的是确定是否会出现批操作中的某些操作可能成功而其它操作可能失败的情况。考虑一个批量删除界面:如果选择的第一条记录删除成功,但第二条由于违反外健约束而失败时,会出现什么情况?第一条记录的删除操作应该回滚?还是可以接受删除第一条记录?
如果想把批操作作为原子操作 对待,即所有的操作步骤要么都成功要么都失败,则需要对数据访问层进行扩展以支持数据库事务 。数据库事务确保INSERT 、UPDATE 和 DELETE 语句集的原子数在事务的保护下执行,大多数当代数据库系统都支持数据库事务特性。
在本教程中,我们将探讨如何扩展DAL 以使用数据库事务。后面的教程将详细探讨为批量插入、更新和删除界面的web 页面实现。 让我们开始吧 !
注意 : 在批事务里修改数据时,原子数并非是必要的。在某些情况下,在同一批处理中,某些数据修改成功某些修改失败是可以接受的,比如,从基于web 的邮件客户端删除一批邮件时。如果在删除过程中出现了数据库错误,对于没有发生错误的记录,仍然保持删除是可以接受的。对于这种情况,没有必要修改DAL 以支持数据库事务。不过在其它批操作情况下,原子数是至关重要的。某个客户想把资金从一个银行账户转到另一个账户时,必须执行两个操作:将第一个账户上的资金扣除,然后添加到第二个账户。如果第一步成功但第二步失败,银行可以不介意,不过客户肯定要心烦意乱了。在后面的三篇教程中,我们将创建插入、更新和删除的批处理界面,就算您不打算在这些页面中使用数据库事务,我也希望您照着本教程,对DAL 进行扩展以支持数据库事务。
事务概述
大多数数据库都支持事务,它可以把多个数据库命令当成一个逻辑单元进行处理。保证组成事务的数据库命令是原子级表示所有的命令要么都失败要么都成功。
一般来说,事务通过 SQL 语句来实现,使用如下的模式:
指示事务的开始。
执行构成事务的 SQL 语句。
如果步骤 2 中的一个语句出错,则回退该事务。
如果步骤 2 中的所有语句都没有错误, 则提交该事务。
用于创建、提交和回退事务的 SQL 语句可通过手动输入,比如写 SQL 脚本或创建存储过程,或使用 ADO.NET 或System.Transactions 命名空间 的类通过编程的方式来构建。在本教程中,我们仅探讨使用ADO.NET 管理事务。在后面的教程中,我们将探讨如何在数据库访问层使用存储过程,那时,我们再仔细探讨创建、回退和提交事务的SQL 语句。同时,更多信息请参考在 SQL Server 存储过程中管理事务 。
注意 :System.Transactions 命名空间的 TransactionScope 类 允许开发人员通过编程的方式将一系列语句封装到事务中,它支持涉及多个源的复杂事务,比如两个不同的数据库,甚至不同类型的数据存储,比如Microsoft SQL Server 数据库、Oracle 数据库和 Web service 。本教程我们使用 ADO.NET 事务而非TransactionScope 类,因为 ADO.NET 对于数据库事务更明确,且在多数情况下占用的资源更少。此外,在某些情况下,TransactionScope 类要使用Microsoft Distributed Transaction Coordinator (MSDTC) 。有关MSDTC 的配置、实现和性能问题是相当专业和高深的课题,不在这些教程的范围内。
在 ADO.NET 中使用SqlClient 提供程序时,通过调用SqlConnection 类 的 BeginTransaction 方法 启动事务,该方法返回一个 SqlTransaction 对象 。构成事务的数据修改语句放在try...catch 块内。如果 try 块内的某个语句出错,执行跳到 catch 块,在此,通过 SqlTransaction 对象的 Rollback 方法 回退事务。如果所有的语句都成功完成,将在try 块后面调用 SqlTransaction 对象的 Commit 方法 提交事务。下面的代码片段说明了该模式。有关在ADO.NET 中使用事务的更多语法和示例,请参考维护与事务的数据库移植性 。
// Create the SqlTransaction object
SqlTransaction myTransaction = SqlConnectionObject.BeginTransaction();
try
{
/*
* ... Perform the database transaction�s data modification statements...
*/
// If we reach here, no errors, so commit the transaction
myTransaction.Commit();
}
catch
{
// If we reach here, there was an error, so rollback the transaction
myTransaction.Rollback();
throw;
}
默认情况下,Typed DataSet 的TableAdapters 不使用事务。要支持事务,我们需要对TableAdapter 类进行扩展,使其包括使用上述模式来执行事务范围内数据修改语句的其他方法。在步骤2 中,我们将探讨如何使用部分类来添加这些方法。
步骤1 :创建批处理数据 Web 页面
在探讨如何扩展 DAL 以支持数据库事务之前,先花点时间来创建一些ASP.NET web 页面,我们在本教程和后面三篇教程中都要用到它们。先添加一个名为BatchData 的新文件夹,然后添加以下 ASP.NET 页面,并将每个页面都与 Site.master 母版页相关联。
Default.aspx
Transactions.aspx
BatchUpdate.aspx
BatchDelete.aspx
BatchInsert.aspx
图1 :为 SqlDataSource 相关的教程添加 ASP.NET 页面
与其它文件夹一样,Default.aspx 将使用SectionLevelTutorialListing.ascx 用户控件列出本部分的教程。因此,从Solution Explorer 中将该用户控件拖到页面的 Design 视图中,从而向Default.aspx 添加该控件。