事务是一组组合成逻辑工作单元的数据库操作_第1页
事务是一组组合成逻辑工作单元的数据库操作_第2页
事务是一组组合成逻辑工作单元的数据库操作_第3页
事务是一组组合成逻辑工作单元的数据库操作_第4页
事务是一组组合成逻辑工作单元的数据库操作_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、完整版 事务是一组组合成逻辑工作单元的数据库操作,在系统执行过程中可能会出错,但事务将控制和维护每个数据库的一致性和完整性。事务处理的主要特征是,任务要么全部完成,要么都不完成。在写入一些记录时,要么写入所有记录,要么什么都不写入。如果在写入一个记录时出现了一个失败,那么在事务处理中已写入的其他数据就会回滚。事务可能由很多单个任务构成。简单事务的一个常见例子:把钱从A账户转到B账户,这涉及两项任务,即从A账户把钱取出来;把钱存入B账户。两项任务要么同时成功,要么一起失败,给予回滚,以便保持账户的状态和原来相同。否则,在执行某一个操作的时候可能会因为停电、网络中断等原因而出现故障,所以

2、有可能更新了一个表中的行,但没有更新相关表中的行。如果数据库支持事务,则可以将数据库操作组成一个事务,以防止因这些事件而使数据库出现不一致。事务的ACID属性如下。l  原子性(Atomicity):事务的所有操作是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。原子性消除了系统处理操作子集的可能性。l  一致性(Consistency):数据从一种正确状态转换到另一种正确状态。事务在完成时,必须使所有的数据都保持一致。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。当事务结束时,所有的内部数据结构都必须是正确的。在存款取款的例子中,逻辑

3、规则是,钱是不能凭空产生或销毁的,对于每个(收支)条目必须有一个相应的抵衡条目产生,以保证账户是平的。l  隔离性(Isolation):由并发事务所作的修改必须与任何其他并发事务所作的修改隔离。查看数据时数据所处的状态,要么是事务修改它之前的状态,要么是事务修改它之后的状态。简单的理解就是,防止多个并发更新彼此干扰。事务在操作数据时与其他事务操作隔离。隔离性一般是通过加锁的机制来实现的。l  持久性(Durability):事务完成之后,它对于系统的影响是永久性的。已提交的更改即使在发生故障时也依然存在。对于事务的开发,.NET平台也为我们提供了几种非常简单方便的事务机制

4、。无论是在功能上还是性能上都提供了优秀的企业级事务支持。.NET开发者可以使用以下5种事务机制: 1、  SQL和存储过程级别的事务。(目前我在用)2、 ADO.NET级别的事务。(目前我在用)3、  ASP.NET页面级别的事务。(目前我在用)4、 企业级服务COM+事务。(没用过啊)5、  System.Transactions 事务处理。(目前我在用) 这5种事务机制有着各自的优势和劣势,分别表现在性能、代码数量和部署设置等方面。开发人员可以根据项目的实际情况选择相应的事务机制。下面就开始分别说明日常开发中5种事务的具体使用。&

5、#160; -目前正在用的方法,推荐! 在 .NET Framework 2.0中增加了System.Transactions,这是一种新的命名空间,完全专注于控制事务性行为。引入了执行事务性工作的更简单方法及一些新的性能优化。System.Transactions提供了一个“轻量级”的、易于使用的Transaction框架。在上节中,要实现Transaction需要利用EnterpriseServices,让组件从ServiceComponent继承下来。而通过System.Transactions,则只要简单的几行代码,不需要继承,不需要Attribute标记。用户根本

6、不需要考虑是简单事务还是分布式事务。新模型会自动根据事务中涉及的对象资源判断使用何种事务管理器。简而言之,对于任何的事务,用户只要使用同一种方法进行处理即可。下面介绍System.Transactions的几种用法。首先要引用:using System.Transactions;。其次,将事务操作代码放在TransactionScope中执行。如: using (TransactionScope ts = new TransactionScope() /事务操作代码 ts.Complete();代码示例:这是最简单,也是最常见的用法。创建了新的 TransactionScope 对象后,即开始

7、创建事务范围。如代码示例所示,建议使用 using 语句创建范围。位于 using 块内的所有操作将成为一个事务的一部分,因为它们共享其所定义的事务执行上下文。本例中的最后一行,调用 TransactionScope 的 Complete 方法,将导致退出该块时请求提交该事务。此方法还提供了内置的错误处理,出现异常时会终止事务。 (示例位置:光盘codech0504ClassTranOrderData3)using (TransactionScope ts = new TransactionScope()/使整个代码块成为事务性代码 #region 在这里编写需要具备Transaction的代

8、码 string msg = "" string conString = "data source=;database=codematic;user id=sa;password=" SqlConnection myConnection = new SqlConnection(conString); myConnection.Open(); SqlCommand myCommand = new SqlCommand(); myCommand.Connection = myConnection; try myCommand.Command

9、Text = "update P_Product set Name='电脑2' where Id=52" myCommand.ExecuteNonQuery(); myCommand.CommandText = "update P_Product set Name='电脑3' where Id=53" myCommand.ExecuteNonQuery(); msg = "成功!" catch (Exception ex) msg = "失败:" + ex.Message; fina

10、lly myConnection.Close(); #endregion ts.Complete(); return msg; 上面的代码演示了在一个Transaction Scope里面打开一个数据库连接的过程。这个数据库连接由于处在一个Transaction Scope里面,所以会自动获得Transaction的能力。如果这里数据库连接的是SQL Server 2005,那么这个Transaction将不会激活一个MSDTC管理的分布式事务,而是会由.NET创建一个Local Transaction,性能非常高。但是如果是SQL Server 2000,则会自动激活一个分布式事务,在性能上

11、会受一定的损失。再看下面的例子:void MethodMoreConn() using (TransactionScope ts = new TransactionScope() using (SqlConnection conn = new SqlConnection(conString1) conn.Open(); using (SqlConnection conn2 = new SqlConnection(conString2) conn2.Open(); ts.Complete(); 这个例子更加充分地说明了Transaction Scope的强大,两个数据库连接!虽然上面的conn和

12、conn2是两个不同的连接对象,可能分别连接到不同的数据库,但是由于它们处在一个TransactionScope中,它们就具备了“联动”的Transaction能力。在这里,将自动激活一个MSDTC管理的分布式事务(可以通过打开【管理工具】里面的组件服务,来查看当前的分布式事务列表)。1在分布式事务中登记ADO.NET 2.0 中的新增功能支持使用 EnlistTransaction 方法在分布式事务中登记。由于 EnlistTransaction 在 Transaction 实例中登记连接,因此,该方法利用 System.Transactions 命名空间中的可用功能来管理分布式事务,从而比

13、使用 System.EnterpriseServices. ITransaction 对象的 EnlistDistributedTransaction 更可取。此外,其语义也稍有不同:在一个事务中显式登记了某个连接后,如果第一个事务尚未完成,则无法取消登记或在另一个事务中登记该连接。void MethodEnlist() CommittableTransaction tx = new CommittableTransaction(); using (SqlConnection conn = new SqlConnection(conString) conn.EnlistTransaction(

14、tx); tx.Commit();2实现嵌套事务范围void RootMethod() using (TransactionScope scope = new TransactionScope() /操作代码 SonMethod();/子事务方法 scope.Complete(); void SonMethod() using (TransactionScope scope = new TransactionScope() /操作代码 scope.Complete(); 3事务范围附加选项如果你想要保留代码部分执行的操作,并且在操作失败的情况下不希望中止环境事务,则Suppress对你很有帮助

15、。例如,在你想要执行日志记录或审核操作时,不管你的环境事务是提交还是中止,上述值都很有用。该值允许你在事务范围内具有非事务性的代码部分,如以下示例所示。void MethodSuppress() using (TransactionScope scope1 = new TransactionScope()/开始事务 try /开始一个非事务范围 using (TransactionScope scope2 = new TransactionScope(TransactionScopeOption.Suppress) /不受事务控制代码 /从这里开始又回归事务处理 catch 虽然.NET 2.

16、0对事务提供了很好的支持,但是没有必要总是使用事务。使用事务的第一条规则是,在能够使用事务的时候都应该使用事务,但是不要使用过度。原因在于,每次使用事务都会占用一定的开销。另外,事务可能会锁定一些表的行。还有一条规则是,只有当操作需要的时候才使用事务。例如,如果只是从数据库中查询一些记录,或者执行单个查询,则在大部分时候都不需要使用显式事务。 开发人员应该在头脑中始终保持一个概念,就是用于修改多个不同表数据的冗长事务会严重妨碍系统中的所有其他用户。这很可能导致一些性能问题。当实现一个事务时,遵循下面的实践经验能够达到可接受的结果:l  避免使用在事务中的Select返回数据,除非语句

17、依赖于返回数据。l  如果使用Select语句,则只选择需要的行,这样不会锁定过多的资源,而尽可能地提高性能。l  尽量将事务全部写在T-SQL或者API中。l  避免事务与多重独立的批处理工作结合,应该将这些批处理放置在单独的事务中。l  尽可能避免大量更新。 另外,必须注意的一点就是事务的默认行为。在默认情况下,如果没有显式地提交事务,则事务会回滚。虽然默认行为允许事务的回滚,但是显式回滚方法总是一个良好的编程习惯。这不仅仅只是释放锁定数据,也将使得代码更容易读取并且更少错误。      .NET提供

18、的事务功能很强大,具体的内容远不止本文所讲解的这样简单。本文只是起到一个抛砖引玉的功能。希望读者能够灵活恰当地使用事务功能,而不要过度使用事务,否则可能会对性能起到消极的作用。     - 现在我们对事务的概念和原理都有所了解了,并且作为已经有一些基础的C#开发者,我们已经熟知编写数据库交互程序的一些要点,即:(1)使用SqlConnection类的对象的Open()方法建立与数据库服务器的连接。(2)然后将该连接赋给SqlCommand对象的Connection属性。(3)将欲执行的SQL语句赋给SqlCommand的Command

19、Text属性。(4)通过SqlCommand对象进行数据库操作。创建一个ADO.NET事务是很简单的,需要定义一个SqlTransaction类型的对象。SqlConnection 和OleDbConnection对象都有一个 BeginTransaction 方法,它可以返回 SqlTransaction 或者OleDbTransaction 对象。然后赋给SqlCommand对象的Transcation属性,即实现了二者的关联。为了使事务处理可以成功完成,必须调用SqlTransaction对象的Commit()方法。如果有错误,则必须调用Rollback()方法撤销所有的操作。代码示例:

20、基于以上认识,下面我们就开始动手写一个基于ADO.NET的事务处理程序。 (示例位置:光盘codech0504WebWebForm2)string conString = "data source=;database=codematic;user id=sa;password="SqlConnection myConnection = new SqlConnection(conString);myConnection.Open(); /启动一个事务SqlTransaction myTrans = myConnection.BeginTransac

21、tion(); /为事务创建一个命令SqlCommand myCommand = new SqlCommand();myCommand.Connection = myConnection;myCommand.Transaction = myTrans;try myCommand.CommandText = "update P_Product set Name='电脑2' where Id=52" myCommand.ExecuteNonQuery(); myCommand.CommandText = "update P_Product s

22、et Name='电脑3' where Id=53" myCommand.ExecuteNonQuery(); myTrans.Commit();/提交 Response.Write("两条数据更新成功");catch (Exception ex) myTrans.Rollback();/遇到错误,回滚 Response.Write(ex.ToString(); finally myConnection.Close();ADO.NET事务的优势和限制如下。优势:l  简单。l  和数据库事务差不多快。l  事务可以跨越

23、多个数据库访问。l  独立于数据库,不同数据库的专有代码被隐藏了。限制:事务执行在数据库连接层上,所以需要在执行事务的过程中手动地维护一个连接。注 意所有命令都必须关联在同一个连接实例上,ADO.NET事务处理不支持跨多个连接的事务处理。   - .NET Framework 依靠 MTS/COM+ 服务来支持自动事务处理。COM+ 使用 Microsoft Distributed Transaction Coordinator(DTC)作为事务管理器和事务协调器在分布式环境中运行事务。这样可使 .NET 应用程序运行跨多个资源结合不同操作(例

24、如将定单插入SQL Server 数据库、将消息写入 Microsoft 消息队列(MSMQ)队列,以及从 Oracle 数据库检索数据)的事务。要实现COM+事务处理的类则必须继承System.EnterpriseServices.ServicedComponent,这些类需要是公共的,并且需要提供一个公共的默认的构造器。其实Web Service就是继承ServicedComponent,所以Web Service也支持COM+事务。要在类定义之前加属性Transaction(TransactionOption.Required)。类里面的每个方法都会运行在一个事务中。定义一个COM+事务

25、处理的类:首先引用:using System.EnterpriseServices;。然后,继承ServicedComponent。Transaction(TransactionOption.Required)public class OrderData : ServicedComponentTransactionOption枚举类型支持5个值:Disabled、NotSupported、Required、RequiresNew和Supported,如表5-3所示。表5-3 TransactionOption枚举类型支持5个值值说 明Disabled忽略当前上下文中的任何事务NotSuppor

26、ted使用非受控事务在上下文中创建组件Required如果事务存在则共享事务,并且如有必要则创建新事务RequiresNew使用新事务创建组件,而与当前上下文的状态无关Supported如果事务存在,则共享该事务一般来说COM+中的组件需要Required 或Supported。当组件用于记录或查账时RequiresNew 很有用,因为组件应该与活动中其他事务处理的提交或回滚隔离开来。派生类可以重载基类的任意属性。如OrderData选用Required,派生类仍然可以重载并指定RequiresNew或其他值。 COM+事务有手动处理和自动处理两种方式,自动处理就是在所需要自动处理的方法前加上

27、AutoComplete,根据方法的正常或抛出异常决定提交或回滚。手动处理就是调用ContextUtil类中的EnableCommit、SetComplete和SetAbort方法。实现步骤如下。1给程序添加强名1)创建一对密钥 用来创建密钥的工具是称为sn.exe的共享工具。通常通过命令提示运行它,该工具可执行各种任务以生成并提取密钥。我们需要用以下方式来运行sn.exe。 sn k c:key.snk 其中key.snk 代表将保存密钥的文件的名称。它的名称可以是任意的,不过习惯上带有.snk后缀名。 2)签名 这个文件必须在AssemblyKeyFile属性中引用,签名通常是在编译时进行

28、的。签名时,用户可利用C属性通知编译器应该使用正确的密钥文件对DLL进行签名。要做到这一点用户需要打开工程中的AssemblyInfo.cs文件并进行修改。 assembly:AssemblyKeyFile(“.key.snk”)  注 意key.snk文件和项目文件在同一个文件夹内。2手动事务处理创建一个项目用以实现事务处理的业务类ClassTran。代码示例: (示例位置:光盘codech0504ClassTranOrderData1) using System;using System.Data.SqlClient;using System.EnterpriseServices

29、; /企业级服务COM+事务namespace ClassTran Transaction(TransactionOption.Required) public class OrderData1 : ServicedComponent /手动事务 public string WorkTran() try ContextUtil.EnableCommit(); Work1(); Work2(); ContextUtil.SetComplete(); return "成功!" catch (Exception ex) ContextUtil.SetAbort(); return

30、 "失败!" private void Work1() string conString = "data source=;database=codematic;user id=sa;password=" SqlConnection myConnection = new SqlConnection(conString); string strSql = "Insert Into P_Category(CategoryId,Name)values('1','test1')" SqlComm

31、and myCommand = new SqlCommand(strSql, myConnection); myConnection.Open(); int rows = myCommand.ExecuteNonQuery(); myConnection.Close(); private void Work2() string conString = "data source=;database=codematic;user id=sa;password=" SqlConnection myConnection = new SqlConnection(co

32、nString); string strSql = "Insert Into P_Category(CategoryId,Name)values('2','test2')" SqlCommand myCommand = new SqlCommand(strSql, myConnection); myConnection.Open(); int rows = myCommand.ExecuteNonQuery(); myConnection.Close(); 3自动事务处理代码示例:在方法之前增加属性AutoComplete(true),这样如

33、果方法执行时没有异常就默认提交,如果有异常则这个方法就会回滚。 (示例位置:光盘codech0504ClassTranOrderData2)using System;using System.Data.SqlClient;using System.EnterpriseServices;/企业级服务COM+事务namespace ClassTran Transaction(TransactionOption.Required) public class OrderData2 : ServicedComponent /自动事务 AutoComplete(true) public string WorkTran() string msg = "" string conString = "data source=;database=codematic;user id=sa;password=" SqlConnection myConnection = new SqlConnection(conString); myConnection.Open(); SqlCommand myCommand = new

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论