使用ASP.NET开发程序时,不仅可以通过Connection对象或者ObjectContext对象实现事务处理,还可以针对SQL Server数据库定义事务,实现对数据的一致性处理从而保证数据的完整性。在通过ADO.NET的事务操作数据库时,任何一个操作都必须成功完成(提交事务),或者所有操作都必须撤销(回滚事务),这样数据库才维持在事务开始之前的状态。 1.方案分析
在大部分数据库应用程序或网站中,往往存在需要保证其原子性的数据库操作,也就是把这一组操作看成一个整体,如果其中一个操作不成功,那么前面所有操作的结果都将没有意义,而且会造成数据的错误,所以必须将数据恢复到这一组操作开始之前。但有时,硬件故障或其他原因往往会导致这一组操作中的某一环节失败。为了确保这种情况下数据库最终结果的确定性和数据的一致性,绝大多数数据库系统引入了事务机制。
例如,将资金从一个帐户转移到另一个帐户的银行应用中,一个帐户将一定的金额贷记到一个数据库表中,同时另一个帐户将相同的金额借记到另一个数据库表中。但是在操作的过程中有可能因为意外情况,而导致在一个表中更新了一行,但未能在其他表中更新相应行的情况发生。这种情况是客户最不想看到的。
如果数据库支持事务,则可以防止上述情况的发生。即将多个数据库操作组合到一个事务中,以防止数据库中出现不一致。当事务中的某一点发生故障,则所有更新都可以回滚到其事务前状态。如果没有发生故障,则通过以完成状态提交事务来完成更新。
在ADO.NET中,可以在两种事务间进行选择:本地事务和分布式事务。本地事务只涉及一种资源——通常是用户所连接的数据库。开始事务,并把一个或多个命令放在该事务的上下文中,判断整个操作是成功的还是失败的。然后提交该事务,或者退回来重来。分布式事务跨越多个异步资源,并确保要么提交整个事务要么全部撤销,在各个步骤作出的所有修改也是要么全部提交要么全部撤销,分布式事务通过 Microsoft 分布式事务协调程序 (MS DTC) 管理,该协调程序集成了事务中访问的所有资源管理器
对于本地事务,ADO.NET通过大量数据库专用的事务对象来管理,如SQL Server事务的SqlTransaction。首先产生一个事务,并命令与它关联,然后决定结果。对于分布式事务,需要企业服务(Enterprise Server)和被服务的组件。
注意:建议用户只在分布式事务中执行更新、插入和删除,因为这些操作会占用大量的数据库资源。选择语句可能会对数据库资源进行不必要的锁定,在某些方案中,可能需要使用事务进行选择。
事务多用于控制和维护数据库中每个操作的一致性和整体性,而不管系统中可能发生的错误。
在ADO.NET中可通过连接类的BeginTransaction方法创建一个全新的的本地事务。可以为该事务赋一个名称和一个隔离级(关于事务的隔离级请参见本节的补充说明)。假设把该方法映射到BEGIN TRANSACTION的SQL Server实现,则创建事务过程的基本方法如下。
(1)BeginTransaction方法
开始数据库事务,其语法格式如下:
public SqlTransaction BeginTransaction ()
返回值:表示新事务对象。
(2)Transaction属性
获取或设置将在其中执行SqlCommand的SqlTransaction。
public SqlTranssction Transaction { get; set; }
属性值:SqlTranssction默认值为空引用。
(3)Commit方法
提交数据库事务,其语法格式如下:
public override void Commit()
(4)Rollback方法
从挂起状态回滚事务,其语法格式如下:
public override void Rollback()
说明:在以上方法中为了向事务添加命令回滚,设置了命令对象的Transaction属性。但如果把一个命令对象的Transaction属性设置到了一个不是连接到同一个连接的事务对象,在试图执行一个语句时将会抛出一个异常。一旦所有的命令完成执行,调用事务对象的Commit方法完成,或者调用Rollback方法撤销该事务,并回滚所有的变更
通过使用Commit或Rollback方法,可显式地终止一个事务。SqlTransaction类支持事务中有名称的保存点(named savepoint),用它可以恢复事务的某一部分。有名称的保存点利用一个特定的SQL Server特性:SAVE TRANSACTION语句。
2.实施过程
在ASP.NET中,有两种方法可以实现事务。具体方法及其实施过程如下。
在网站后台管理中对网站进行维护与更新时,免不了要执行向多个数据表中同时插入数据的操作。本实例就是在向数据库的3个表中插入数据时引入事务,确保了插入数据最终结果的确定性和数据的一致性。
单击图中的【添加】按钮,程序将会向数据库中的3个数据表同时添加数据,当在执行添加的过程中因某种原因造成了程序的终止,则该程序将恢复到添加之前的状态,数据添加无效。
具体实施过程:
(1)新建一个网站,将其命名为13,默认主页为Default.aspx。
(2)在Default.aspx页中添加9个TextBox控件和两个Button控件,分别用于输入要添加的数据信息、执行添加操作和清空文本框信息。
(3)触发Default.aspx页面中的【添加】按钮的Click事件,在该事件中完成向数据库添加数据操作并引入事务,主要程序代码如下。
protectedvoidButton1_Click(objectsender,EventArgse)
{
if(TextBox1.Text==""||TextBox2.Text==""||TextBox3.Text==""
||TextBox4.Text==""||TextBox5.Text==""||TextBox6.Text==
""||TextBox7.Text==""||TextBox8.Text==""||TextBox9.Text=="")
{
Response.Write("<scriptlanguage=javascript>alert('不允许输入空数据!');
location='javascript:history.go(-1)'</script>");
}
SqlConnectioncon=newSqlConnection("server=(local);userid
=sa;pwd=;DataBase=db_07");
con.Open();
//通过SqlConnection的BeginTransaction方法创建名为st的对象Transaction
SqlTransactionst=con.BeginTransaction();
SqlCommandcom=con.CreateCommand();
//将SqlTransaction对象分配给SqlCommand对象的Transaction属性
com.Transaction=st;
try
{
//向表1插入数据
com.CommandText="insertintotb_21a(name,age,sex)values('"+
TextBox1.Text+"','"+TextBox2.Text+"','"+TextBox3.Text+"')";
com.ExecuteNonQuery();
//向表2插入数据
com.CommandText="insertintotb_21b(name,age,sex)values('"+
TextBox4.Text+"','"+TextBox5.Text+"','"+TextBox6.Text+"')";
com.ExecuteNonQuery();
//向表3插入数据
com.CommandText="insertintotb_21c(name,age,sex)values('"+TextBox7.
Text+"','"+TextBox8.Text+"','"+TextBox9.Text+"')";
com.ExecuteNonQuery();
//提交事物
st.Commit();
Response.Write("<scriptlanguage=javascript>alert('添加成功!');
location='javascript:history.go(-1)'</script>");
}
catch(Exceptionerror)
{
//回滚事物
st.Rollback();
}
finally
{
con.Close();
}
}
注意:在编写代码前,不要忘记先引用using System.Data.SqlClient命名空间。 方案实施二,通过在存储过程中使用事务对数据库进行操作