很自然,我们最后看到了输出"事务处理已经成功完成",再用企业管理器查看pubs数据库的roysched表,所有title_id字段以"PC"开头的书籍的royalty字段的值都增加了0.1倍。
这里,我们并没有使用ADO.net的事务处理机制,而是简单地将执行事务的SQL语句当作普通的查询来执行,因此,事实上该事务完全没有用到.net的相关特性。 了解.net中的事务机制
如你所知,在.net框架中主要有两个命名空间(namespace)用于应用程序同数据库系统的交互:System.Data.SqlClient和System.Data.OleDb。前者专门用于连接Microsoft公司自己的SQL Server数据库,而后者可以适应多种不同的数据库。这两个命名空间中都包含有专门用于管理数据库事务的类,分别是System.Data.SqlClient.SqlTranscation类和System.Data.OleDb.OleDbTranscation类。
就像它们的名字一样,这两个类大部分功能是一样的,二者之间的主要差别在于它们的连接机制,前者提供一组直接调用 SQL Server 的对象,而后者使用本机 OLE DB 启用数据访问。 事实上,ADO.net 事务完全在数据库的内部处理,且不受 Microsoft 分布式事务处理协调器 (DTC) 或任何其他事务性机制的支持。本文将主要介绍System.Data.SqlClient.SqlTranscation类,下面的段落中,除了特别注明,都将使用System.Data.SqlClient.SqlTranscation类。
事务的开启和提交
现在我们对事务的概念和原理都了然于心了,并且作为已经有一些基础的C#开发者,我们已经熟知编写数据库交互程序的一些要点,即使用SqlConnection类的对象的Open()方法建立与数据库服务器的连接,然后将该连接赋给SqlCommand对象的Connection属性,将欲执行的SQL语句赋给它的CommandText属性,于是就可以通过SqlCommand对象进行数据库操作了。对于我们将要编写的事务处理程序,当然还需要定义一个SqlTransaction类型的对象。并且看到SqlCommand对象的Transcation属性,我们很容易想到新建的SqlTransaction对象应该与它关联起来。
基于以上认识,下面我们就开始动手写我们的第一个事务处理程序。我们可以很熟练地写出下面这一段程序:
//DoTran.csusing System; using System.Data; using System.Data.SqlClient; namespace Aspcn { public class DbTran { file://执行事务处理 public void DoTran() { file://建立连接并打开 SqlConnection myConn=GetConn(); myConn.Open(); SqlCommand myComm=new SqlCommand(); SqlTransaction myTran=new SqlTransaction(); try { myComm.Connection=myConn; myComm.Transaction=myTran; file://定位到pubs数据库 myComm.CommandText="USE pubs"; myComm.ExecuteNonQuery();
file://更新数据 file://将所有的计算机类图书 myComm.CommandText="UPDATE roysched SET royalty = royalty * 1.10 WHERE title_id LIKE ’Pc%’"; myComm.ExecuteNonQuery();//提交事务 myTran.Commit(); } catch(Exception err) { throw new ApplicationException("事务操作出错,系统信息:"+err.Message); } finally { myConn.Close(); } } file://获取数据连接 private SqlConnection GetConn() { string strSql="Data Source=localhost;Integrated Security=SSPI;user id=sa;password="; SqlConnection myConn=new SqlConnection(strSql); return myConn; } }
public class Test{public static void Main() { DbTran tranTest=new DbTran(); tranTest.DoTran(); Console.WriteLine("事务处理已经成功完成。"); Console.ReadLine(); } } }
显然,这个程序非常简单,我们非常自信地编译它,但是,出乎意料的结果使我们的成就感顿时烟消云散:
error CS1501: 重载"SqlTransaction"方法未获取"0"参数
是什么原因呢?注意到我们初始化的代码:
SqlTransaction myTran=new SqlTransaction();
显然,问题出在这里,事实上,SqlTransaction类并没有公共的构造函数,我们不能这样新建一个SqlTrancaction类型的变量。在事务处理之前确实需要有一个SqlTransaction类型的变量,将该变量关联到SqlCommand类的Transcation属性也是必要的,但是初始化方法却比较特别一点。在初始化SqlTransaction类时,你需要使用SqlConnection类的BeginTranscation()方法:
SqlTransaction myTran; myTran=myConn.BeginTransaction();
该方法返回一个SqlTransaction类型的变量。在调用BeginTransaction()方法以后,所有基于该数据连接对象的SQL语句执行动作都将被认为是事务MyTran的一部分。同时,你也可以在该方法的参数中指定事务隔离级别和事务名称,如:
SqlTransaction myTran; myTran=myConn.BeginTransaction(IsolationLevel.ReadCommitted,"SampleTransaction");
关于隔离级别的概念我们将在随后的内容中探讨,在这里我们只需牢记一个事务是如何被启动,并且关联到特定的数据链接的。
先不要急着去搞懂我们的事务都干了些什么,看到这一行:
myTran.Commit();
是的,这就是事务的提交方式。该语句执行后,事务的所有数据库操作将生效,并且为数据库事务的持久性机制所保持--即使系统在这以后发生致命错误,该事务对数据库的影响也不会消失。
对上面的程序做了修改之后我们可以得到如下代码(为了节约篇幅,重复之处已省略,请参照前文):
//DoTran.cs……}
file://执行事务处理 public void DoTran() { file://建立连接并打开 SqlConnection myConn=GetConn(); myConn.Open(); SqlCommand myComm=new SqlCommand();
file://SqlTransaction myTran=new SqlTransaction(); file://注意,SqlTransaction类无公开的构造函数
SqlTransaction myTran;
file://创建一个事务 myTran=myConn.BeginTransaction(); try { file://从此开始,基于该连接的数据操作都被认为是事务的一部分 file://下面绑定连接和事务对象 myComm.Connection=myConn; myComm.Transaction=myTran; file://定位到pubs数据库 myComm.CommandText="USE pubs"; myComm.ExecuteNonQuery();//更新数据 file://将所有的计算机类图书 myComm.CommandText="UPDATE roysched SET royalty = royalty * 1.10 WHERE title_id LIKE ’Pc%’"; myComm.ExecuteNonQuery(); file://提交事务 myTran.Commit(); } catch(Exception err) { throw new ApplicationException("事务操作出错,系统信息:"+err.Message); } finally { myConn.Close(); } } ……
到此为止,我们仅仅掌握了如何开始和提交事务。下一步我们必须考虑的是在事务中可以干什么和不可以干什么。 
说明:本教程来源互联网或网友上传或出版商,仅为学习研究或媒体推广,wanshiok.com不保证资料的完整性。
2/2 首页 上一页 1 2 |