事务在C语言中如何实现多线程处理?

2026-04-27 12:451阅读0评论SEO基础
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计3479个文字,预计阅读时间需要14分钟。

事务在C语言中如何实现多线程处理?

目录

一、概述

1.事务ACID特性

二、.NET开发者用到的5种事务机制:

1.数据库事务

1.1 不同数据库的事务规则 1.2 数据库事务的优势和限制 1.1 优势 1.2 限制

2.ADO.NET事务

3.System事务

目录
  • 一、概述
    • 1、事务ACID特性
    • 2、.NET开发者用到的5种事务机制:
  • 二、数据库事务
    • 1、不同数据库的事务规则
    • 2、数据库事务的优势和限制
    • (1)优势:
    • (2)限制:
  • 三、ADO.Net事务
    • 四、System.EnterpriseServices自动事务处理
      • 五、System.Transactions事务
        • 1、显式事务(Explicit Transaction)
        • 2、Transaction类的派生类
        • 3、Transaction类成员
      • 六、可提交的事务:CommitableTransaction(显式事务)
        • 七、环境事务:TrasactionScope(隐式事务,推荐)
          • 1、隔离级别IsolationLevel
          • 2、嵌套环境事务
          • 3、TransactionScopeOption
          • 4、MSDTC组件设置:
        • 八、依赖事务DependentTransaction,跨多个线程调用事务(显式事务)

          一、概述

          1、事务ACID特性

          事务将一系列的工作视为一个工作单元,它具有 ACID 特性:

          • A:Atomicity 不可分性
            也就是说事务中有多项工作,如果有一项工作失败了,整个事务就算失败了。
          • C:Consistency 一致性
            事务完成时,全部数据必须维持一致性的状态。对于关系数据库,简单地来说就是没有破坏数据完整性。
          • I:Isolation 隔离性
            事务与其他事务是隔离的,也就是说一个事务的一项工作对数据进行修改时,如果整个事务还没有结束,其他事务就无法知道这个数据发生了修改。
          • D:Durability 持久性
            事务完成后,其作用便永远存在于系统之中。

          2、.NET开发者用到的5种事务机制:

          • SQL和存储过程级别的事务。(数据库事务)
          • ADO.NET级别的事务。
          • ASP.NET页面级别的事务。
          • 企业级服务COM+事务。
          • System.Transactions 事务处理。

          这5种事务机制有着各自的优势和劣势,分别表现在性能、代码数量和部署设置等方面。开发人员可以根据项目的实际情况选择相应的事务机制。

          二、数据库事务

          1、不同数据库的事务规则

          数据库事务是其他事务模型的基础,当一个事务创建时不同数据库系统都有自己的规则。

          事务在C语言中如何实现多线程处理?

          • SQL Server默认在自动提交的模式下工作,每个语句执行完后都会立即提交;
          • Oracle则需要你包含一个提交语句。
          • 当一个语句通过OLE DB执行时,它执行完后一个提交动作会被附加上去。

          例如:SQL Server数据库T-SQL语句中显示指定事务

          declare @TranName varchar(20); select @TranName = 'MyTransaction'; begin transaction @TranName; go use AdventureWorks; go delete from AdventureWorks.HumanResources.JobCandidate where JobCandidateID = 13; go commit transaction MyTransaction; go

          或在存储过程中使用

          create procedure Tran1 as begin tran; set xact_abort on; --set xact_abort on表示遇到错误立即回滚。 insert into P_Category ( CategoryId, Name ) values ( '1', 'test1' ); insert into P_Category ( CategoryId, Name ) values ( '2', 'test2' ); commit tran; go

          2、数据库事务的优势和限制

          (1)优势:

          • 所有的事务逻辑包含在一个单独的调用中。
          • 拥有运行一个事务的最佳性能。
          • 独立于应用程序。

          (2)限制:

          • 事务上下文仅存在于数据库调用中。
          • 数据库代码与数据库系统有关。

          三、ADO.Net事务

          ADO.Net事务为System.Data.Common.DbTransaction类的各种派生类。ADO.Net事务不是分布式事务,不支持跨多个连接,它总是关联到一个连接上的本地事务上。

          ADO.NET 显式事务占用资源少、速度快,但功能简单,只能管理单一对象和单一持久资源间的事务。

          using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MySqlServer"].ConnectionString)) { conn.Open(); using (SqlTransaction tran = conn.BeginTransaction()) { using (SqlCommand cmd = new SqlCommand()) { cmd.Connection = conn; cmd.Transaction = tran; cmd.CommandType = CommandType.Text; try { cmd.CommandText = "insert into TranTable(Priority) values(1)"; cmd.ExecuteNonQuery(); cmd.CommandText = "insert into TranTable(Priority) values(256)"; cmd.ExecuteNonQuery(); tran.Commit(); Response.Write("Ok"); } catch (SqlException ex) { tran.Rollback(); Response.Write("Error:" + ex.Message); } } } conn.Close(); }

          四、System.EnterpriseServices自动事务处理

          不需要显示进行事务处理,运行库自动创建事务。多个对象能轻松的运行在同一个事务中。但它需要COM+主机模型。

          使用此技术的类必须派生自ServicedComponen类。

          [Transaction(TransactionOption.Required)] public class OrderContrl : ServicedComponent { [AutoComplete] public void NewOrder(Order order) { using (OrderData data = new OrderData()) { data.Insert(order); } } }

          五、System.Transactions事务

          System.Transactions是所有事务处理类的基类。

          System.Transactions基础结构通过支持SQL Server、ADO.NET、MSMQ和Microsoft分布式事务协调器(MSDTC)中启动的事务,使得整个平台的事务编程变得简单和高效。

          它既提供了基于Transaction 类的显式编程模型,也提供了使用TransactionScope类的隐式编程模型,它里面的事务由基础设施自动管理。强烈建议使用更简单的隐式开发模型TransactionScope。

          1、显式事务(Explicit Transaction)

          提交、回滚事务都由程序员编程来决定的方式,叫“显式事务(Explicit Transaction)”。Transaction 类及其派生类为显式事务。

          2、Transaction类的派生类

          • CommittableTransaction:可提交的事务
          • DependentTransaction:依赖事务
          • SubordinateTransaction:可以委托的下属事务

          3、Transaction类成员

          • Current:获取或设置环境事务。
          • IsolationLevel:获取事务的隔离级别。
          • TransactionInformation:检索有关某个事务的附加信息。
          • DependentClone(DependentCloneOption) :创建事务的依赖复本。
          • Rollback() :回滚(中止)事务。
          • Dispose():释放由该对象占用的资源。
          • TransactionCompleted:指示事务已完成。

          六、可提交的事务:CommitableTransaction(显式事务)

          唯一支持提交的事务类是CommitableTransaction,它直接继承自Transaction。

          CommittableTransaction提供了“Commit”同步方法和“BeginCommit”、“EndCommit”异步方法组合对事务的提交。

          创建CommittableTransaction事务并不会自动设置环境事务。

          CommittableTransaction事务不能被重用。可以将数据库连接登记到事务。

          注意:只有一个DbConnection时为本地事务;当存在多个DbConnection时才会启动MSDTC(MSDTC不够稳定,尽量避免引入分布式服务)

          using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MySqlServer"].ConnectionString)) { using (CommittableTransaction ct = new CommittableTransaction ()) { conn.Open(); conn.EnlistTransaction(ct);//将数据库连接登记到事务 using (SqlCommand cmd = new SqlCommand()) { cmd.Connection = conn; cmd.CommandType = CommandType.Text; try { cmd.CommandText = "insert into TranTable(Priority) values(1)"; cmd.ExecuteNonQuery(); cmd.CommandText = "insert into TranTable(Priority) values(256)"; cmd.ExecuteNonQuery(); ct.Commit(); //提交事务 Response.Write("Ok"); } catch (SqlException ex) { ct.Rollback();//回滚事务 Response.Write("Error:" + ex.Message); } } conn.Close(); } }

          七、环境事务:TrasactionScope(隐式事务,推荐)

          TransactionScope为隐式事务。它为一组事务型操作创建一个执行范围,而这个范围始于TransactionScope创建之时,结束于TransactionScope被回收(调用Dispose方法)。

          TransactionScope实现了IDisposable接口,除了Dispose方法之外,仅仅具有一个唯一的方法:Complete()。

          目前 TransactionScope 只能处理数据库的事务,对于其他事务,如 I/O,目前的 .NET 版本无法处理。

          using (SqlConnection conn = new SqlConnection("Data Source=.; Initial Catalog=TestDb; Integrated Security=SSPI;")) { using (TransactionScope ts = new TransactionScope()) { conn.Open(); try { SqlCommand cmd = new SqlCommand(conn); cmd.CommandText = "INSERT INTO [Test]([Name],[Value]) VALUES ('测试1','1')"; cmd.ExecuteNonQuery(); cmd.CommandText = "INSERT INTO [Test]([Name],[Value]) VALUES ('测试2','2')"; cmd.ExecuteNonQuery(); ts.Complete(); } catch (SqlException) { } conn.Close(); } }

          TransactionScope却有一组丰富的构造函数。我们先来看看这些构造函数相应的参数如何影响TransactionScope对事务控制的行为。

          void Main() { TransactionOptions transactionOptions = new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 2, 0)//超时间隔两分钟 }; using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) { Transaction.Current.TransactionCompleted += (sender, args) => { Console.Write(args.Transaction.TransactionInformation.LocalIdentifier); } AddStudent(new Student { }); scope.Complete();//提交事务 } } public void AddStudent(Student s) { SqlConnection conn = new SqlConnection();//环境事务内新建的连接自动附加到事务 //如果连接在TransactionScope建立之前已存在,需要手工用conn.EnlistTrasaction(Transaction.Current)登记事务 conn.Open(); try { SqlCommand command = new SqlCommand(); } catch (Exception ex) { throw; } }

          1、隔离级别IsolationLevel

          7个隔离级别之中,Serializable具有最高隔离级别,代表的是一种完全基于序列化(同步)的数据存取方式。按照隔离级别至高向低,7个不同的隔离级别代表的含义如下:

          • Serializable:可序列化。(默认,最高级别)可以在事务期间读取可变数据,但是不可以修改,也不可以添加任何新数据;
          • RepeatableRead:可重复读。可以在事务期间读取可变数据,但是不可以修改。可以在事务期间添加新数据;
          • ReadCommitted:可读已提交的数据。不可以在事务期间读取可变数据,但是可以修改它;
          • ReadUncommitted:读未提交的数据。可以在事务期间读取和修改可变数据;
          • Snapshot:快照。可以读取可变数据。在事务修改数据之前,它验证在它最初读取数据之后另一个事务是否更改过这些数据。如果数据已被更新,则会引发错误。这样使事务可获取先前提交的数据值;
          • Chaos:混乱。无法覆盖隔离级别更高的事务中的挂起的更改;
          • Unspecified:未指定。正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别。如果设置了此值,则会引发异常。

          2、嵌套环境事务

          using (TransactionScope outerScope = new TransactionScope()) { using (TransactionScope innerScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) { //事务型操作 innerScope.Complete(); } //事务型操作 outerScope.Complete(); }

          3、TransactionScopeOption

          使用TransactionScopeOptions可以改变TransactionScope的默认事务类型。

          • Required:(默认)如果已经存在一个事务,那么这个事务范围将加入已有的事务。否则,它将创建自己的事务。
          • RequiresNew:这个事务范围将创建自己的事务。
          • Suppress:抑制。 将事务范围内的环境事务设为空,意味着事务范围内的操作并不受事务的控制。当部分代码需要留在事务外部时,可以使用该选项。

          4、MSDTC组件设置:

          一般情况下只要你使用"TransactionScope",都要配置MSDTC,要配防火墙,要开139端口,这个端口不可以更改。

          • 如果WEB服务器和数据库是在同一台服务器上,TransactionScope使用的是本地事务,这时不需要配置MSDTC。
          • 如果WEB服务器和数据库不在同一台服务器上,TransactionScope会自动提升事务级别为分布式事务,这时就需要配置MSDTC。

          对MSDTC组件设置:控制面板--->管理工具--->服务 中,开启Distributed Transaction Coordinator 服务。

          • 控制面板->管理工具->组件服务->计算机->我的电脑->右键->属性,选择MSDTC页, 确认"使用本地协调器"。
          • 点击下方"安全配置"按钮
          • 勾选: "允许网络DTC访问","允许远程客户端","允许入站","允许出站","不要求进行身份验证".
          • 对于数据库服务器端, 可选择"要求对呼叫方验证"
          • 勾选:"启用事务Internet协议(TIP)事务"。
          • 在双方防火墙中增加MSDTC.exe例外
            可用命令行: netsh firewall set allowedprogram %windir%/system32/msdtc.exe MSDTC enable

          八、依赖事务DependentTransaction,跨多个线程调用事务(显式事务)

          一个环境事务绑定到一个线程上,如果新建了一个线程它就不会有第一个线程中的环境事务,两个线程中的事务完全独立。

          如果多个线程使用同一个环境事务,需要给新线程传递一个依赖事务,调用Transaction的DependentClone方法创建依赖事务。

          依赖事务通过DependentTransaction类型表示,和CommittableTransaction一样,DependentTransaction也是Transaction的子类。

          DependentTransaction依赖于现有的Transaction对象而存在,相当于被依赖事务的子事务,具有一个唯一的方法成员:Complete。调用这个方法意味着向被依赖事务发送通知,表明所有与依赖事务相关的操作已经完成。

          DependentClone方法具有一个DependentCloneOption枚举类型的参数:

          • BlockCommitUntilComplete:表示被依赖事务在提交前会一直等待接收到依赖事务(子事务)的通知(调用Complete或者Rollback方法)或者超过事务设定的超时时限;
          • RollbackIfNotComplete:如果被依赖事务在依赖事务(子事务)之前先完成,直接将被依赖的事务回滚,并抛出TransactionAbortedException异常。

          下面的代码示例演示如何创建一个依赖事务来管理两个并发任务,具体为克隆一个依赖的事务并将其传递给辅助线程。

          void Main() { using (TransactionScope scope = new TransactionScope()) { DependentTransaction dTx = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete); Thread thread = new Thread(ThreadMethod); thread.Start(dTx); /* Do some transactional work here, then: */ scope.Complete(); } } public void ThreadMethod(object transaction) { DependentTransaction dTx = transaction as DependentTransaction; try { //将DependentTransaction对象作为TransactionScope的参数,以初始化环境事务 using (TransactionScope ts = new TransactionScope(dTx)) { /* Perform transactional work here */ ts.Complete();//完成环境事务 } } finally { dTx.Complete();//完成依赖事务 dTx.Dispose(); } }

          到此这篇关于c#事务的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持自由互联。

          本文共计3479个文字,预计阅读时间需要14分钟。

          事务在C语言中如何实现多线程处理?

          目录

          一、概述

          1.事务ACID特性

          二、.NET开发者用到的5种事务机制:

          1.数据库事务

          1.1 不同数据库的事务规则 1.2 数据库事务的优势和限制 1.1 优势 1.2 限制

          2.ADO.NET事务

          3.System事务

          目录
          • 一、概述
            • 1、事务ACID特性
            • 2、.NET开发者用到的5种事务机制:
          • 二、数据库事务
            • 1、不同数据库的事务规则
            • 2、数据库事务的优势和限制
            • (1)优势:
            • (2)限制:
          • 三、ADO.Net事务
            • 四、System.EnterpriseServices自动事务处理
              • 五、System.Transactions事务
                • 1、显式事务(Explicit Transaction)
                • 2、Transaction类的派生类
                • 3、Transaction类成员
              • 六、可提交的事务:CommitableTransaction(显式事务)
                • 七、环境事务:TrasactionScope(隐式事务,推荐)
                  • 1、隔离级别IsolationLevel
                  • 2、嵌套环境事务
                  • 3、TransactionScopeOption
                  • 4、MSDTC组件设置:
                • 八、依赖事务DependentTransaction,跨多个线程调用事务(显式事务)

                  一、概述

                  1、事务ACID特性

                  事务将一系列的工作视为一个工作单元,它具有 ACID 特性:

                  • A:Atomicity 不可分性
                    也就是说事务中有多项工作,如果有一项工作失败了,整个事务就算失败了。
                  • C:Consistency 一致性
                    事务完成时,全部数据必须维持一致性的状态。对于关系数据库,简单地来说就是没有破坏数据完整性。
                  • I:Isolation 隔离性
                    事务与其他事务是隔离的,也就是说一个事务的一项工作对数据进行修改时,如果整个事务还没有结束,其他事务就无法知道这个数据发生了修改。
                  • D:Durability 持久性
                    事务完成后,其作用便永远存在于系统之中。

                  2、.NET开发者用到的5种事务机制:

                  • SQL和存储过程级别的事务。(数据库事务)
                  • ADO.NET级别的事务。
                  • ASP.NET页面级别的事务。
                  • 企业级服务COM+事务。
                  • System.Transactions 事务处理。

                  这5种事务机制有着各自的优势和劣势,分别表现在性能、代码数量和部署设置等方面。开发人员可以根据项目的实际情况选择相应的事务机制。

                  二、数据库事务

                  1、不同数据库的事务规则

                  数据库事务是其他事务模型的基础,当一个事务创建时不同数据库系统都有自己的规则。

                  事务在C语言中如何实现多线程处理?

                  • SQL Server默认在自动提交的模式下工作,每个语句执行完后都会立即提交;
                  • Oracle则需要你包含一个提交语句。
                  • 当一个语句通过OLE DB执行时,它执行完后一个提交动作会被附加上去。

                  例如:SQL Server数据库T-SQL语句中显示指定事务

                  declare @TranName varchar(20); select @TranName = 'MyTransaction'; begin transaction @TranName; go use AdventureWorks; go delete from AdventureWorks.HumanResources.JobCandidate where JobCandidateID = 13; go commit transaction MyTransaction; go

                  或在存储过程中使用

                  create procedure Tran1 as begin tran; set xact_abort on; --set xact_abort on表示遇到错误立即回滚。 insert into P_Category ( CategoryId, Name ) values ( '1', 'test1' ); insert into P_Category ( CategoryId, Name ) values ( '2', 'test2' ); commit tran; go

                  2、数据库事务的优势和限制

                  (1)优势:

                  • 所有的事务逻辑包含在一个单独的调用中。
                  • 拥有运行一个事务的最佳性能。
                  • 独立于应用程序。

                  (2)限制:

                  • 事务上下文仅存在于数据库调用中。
                  • 数据库代码与数据库系统有关。

                  三、ADO.Net事务

                  ADO.Net事务为System.Data.Common.DbTransaction类的各种派生类。ADO.Net事务不是分布式事务,不支持跨多个连接,它总是关联到一个连接上的本地事务上。

                  ADO.NET 显式事务占用资源少、速度快,但功能简单,只能管理单一对象和单一持久资源间的事务。

                  using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MySqlServer"].ConnectionString)) { conn.Open(); using (SqlTransaction tran = conn.BeginTransaction()) { using (SqlCommand cmd = new SqlCommand()) { cmd.Connection = conn; cmd.Transaction = tran; cmd.CommandType = CommandType.Text; try { cmd.CommandText = "insert into TranTable(Priority) values(1)"; cmd.ExecuteNonQuery(); cmd.CommandText = "insert into TranTable(Priority) values(256)"; cmd.ExecuteNonQuery(); tran.Commit(); Response.Write("Ok"); } catch (SqlException ex) { tran.Rollback(); Response.Write("Error:" + ex.Message); } } } conn.Close(); }

                  四、System.EnterpriseServices自动事务处理

                  不需要显示进行事务处理,运行库自动创建事务。多个对象能轻松的运行在同一个事务中。但它需要COM+主机模型。

                  使用此技术的类必须派生自ServicedComponen类。

                  [Transaction(TransactionOption.Required)] public class OrderContrl : ServicedComponent { [AutoComplete] public void NewOrder(Order order) { using (OrderData data = new OrderData()) { data.Insert(order); } } }

                  五、System.Transactions事务

                  System.Transactions是所有事务处理类的基类。

                  System.Transactions基础结构通过支持SQL Server、ADO.NET、MSMQ和Microsoft分布式事务协调器(MSDTC)中启动的事务,使得整个平台的事务编程变得简单和高效。

                  它既提供了基于Transaction 类的显式编程模型,也提供了使用TransactionScope类的隐式编程模型,它里面的事务由基础设施自动管理。强烈建议使用更简单的隐式开发模型TransactionScope。

                  1、显式事务(Explicit Transaction)

                  提交、回滚事务都由程序员编程来决定的方式,叫“显式事务(Explicit Transaction)”。Transaction 类及其派生类为显式事务。

                  2、Transaction类的派生类

                  • CommittableTransaction:可提交的事务
                  • DependentTransaction:依赖事务
                  • SubordinateTransaction:可以委托的下属事务

                  3、Transaction类成员

                  • Current:获取或设置环境事务。
                  • IsolationLevel:获取事务的隔离级别。
                  • TransactionInformation:检索有关某个事务的附加信息。
                  • DependentClone(DependentCloneOption) :创建事务的依赖复本。
                  • Rollback() :回滚(中止)事务。
                  • Dispose():释放由该对象占用的资源。
                  • TransactionCompleted:指示事务已完成。

                  六、可提交的事务:CommitableTransaction(显式事务)

                  唯一支持提交的事务类是CommitableTransaction,它直接继承自Transaction。

                  CommittableTransaction提供了“Commit”同步方法和“BeginCommit”、“EndCommit”异步方法组合对事务的提交。

                  创建CommittableTransaction事务并不会自动设置环境事务。

                  CommittableTransaction事务不能被重用。可以将数据库连接登记到事务。

                  注意:只有一个DbConnection时为本地事务;当存在多个DbConnection时才会启动MSDTC(MSDTC不够稳定,尽量避免引入分布式服务)

                  using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["MySqlServer"].ConnectionString)) { using (CommittableTransaction ct = new CommittableTransaction ()) { conn.Open(); conn.EnlistTransaction(ct);//将数据库连接登记到事务 using (SqlCommand cmd = new SqlCommand()) { cmd.Connection = conn; cmd.CommandType = CommandType.Text; try { cmd.CommandText = "insert into TranTable(Priority) values(1)"; cmd.ExecuteNonQuery(); cmd.CommandText = "insert into TranTable(Priority) values(256)"; cmd.ExecuteNonQuery(); ct.Commit(); //提交事务 Response.Write("Ok"); } catch (SqlException ex) { ct.Rollback();//回滚事务 Response.Write("Error:" + ex.Message); } } conn.Close(); } }

                  七、环境事务:TrasactionScope(隐式事务,推荐)

                  TransactionScope为隐式事务。它为一组事务型操作创建一个执行范围,而这个范围始于TransactionScope创建之时,结束于TransactionScope被回收(调用Dispose方法)。

                  TransactionScope实现了IDisposable接口,除了Dispose方法之外,仅仅具有一个唯一的方法:Complete()。

                  目前 TransactionScope 只能处理数据库的事务,对于其他事务,如 I/O,目前的 .NET 版本无法处理。

                  using (SqlConnection conn = new SqlConnection("Data Source=.; Initial Catalog=TestDb; Integrated Security=SSPI;")) { using (TransactionScope ts = new TransactionScope()) { conn.Open(); try { SqlCommand cmd = new SqlCommand(conn); cmd.CommandText = "INSERT INTO [Test]([Name],[Value]) VALUES ('测试1','1')"; cmd.ExecuteNonQuery(); cmd.CommandText = "INSERT INTO [Test]([Name],[Value]) VALUES ('测试2','2')"; cmd.ExecuteNonQuery(); ts.Complete(); } catch (SqlException) { } conn.Close(); } }

                  TransactionScope却有一组丰富的构造函数。我们先来看看这些构造函数相应的参数如何影响TransactionScope对事务控制的行为。

                  void Main() { TransactionOptions transactionOptions = new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted, Timeout = new TimeSpan(0, 2, 0)//超时间隔两分钟 }; using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) { Transaction.Current.TransactionCompleted += (sender, args) => { Console.Write(args.Transaction.TransactionInformation.LocalIdentifier); } AddStudent(new Student { }); scope.Complete();//提交事务 } } public void AddStudent(Student s) { SqlConnection conn = new SqlConnection();//环境事务内新建的连接自动附加到事务 //如果连接在TransactionScope建立之前已存在,需要手工用conn.EnlistTrasaction(Transaction.Current)登记事务 conn.Open(); try { SqlCommand command = new SqlCommand(); } catch (Exception ex) { throw; } }

                  1、隔离级别IsolationLevel

                  7个隔离级别之中,Serializable具有最高隔离级别,代表的是一种完全基于序列化(同步)的数据存取方式。按照隔离级别至高向低,7个不同的隔离级别代表的含义如下:

                  • Serializable:可序列化。(默认,最高级别)可以在事务期间读取可变数据,但是不可以修改,也不可以添加任何新数据;
                  • RepeatableRead:可重复读。可以在事务期间读取可变数据,但是不可以修改。可以在事务期间添加新数据;
                  • ReadCommitted:可读已提交的数据。不可以在事务期间读取可变数据,但是可以修改它;
                  • ReadUncommitted:读未提交的数据。可以在事务期间读取和修改可变数据;
                  • Snapshot:快照。可以读取可变数据。在事务修改数据之前,它验证在它最初读取数据之后另一个事务是否更改过这些数据。如果数据已被更新,则会引发错误。这样使事务可获取先前提交的数据值;
                  • Chaos:混乱。无法覆盖隔离级别更高的事务中的挂起的更改;
                  • Unspecified:未指定。正在使用与指定隔离级别不同的隔离级别,但是无法确定该级别。如果设置了此值,则会引发异常。

                  2、嵌套环境事务

                  using (TransactionScope outerScope = new TransactionScope()) { using (TransactionScope innerScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) { //事务型操作 innerScope.Complete(); } //事务型操作 outerScope.Complete(); }

                  3、TransactionScopeOption

                  使用TransactionScopeOptions可以改变TransactionScope的默认事务类型。

                  • Required:(默认)如果已经存在一个事务,那么这个事务范围将加入已有的事务。否则,它将创建自己的事务。
                  • RequiresNew:这个事务范围将创建自己的事务。
                  • Suppress:抑制。 将事务范围内的环境事务设为空,意味着事务范围内的操作并不受事务的控制。当部分代码需要留在事务外部时,可以使用该选项。

                  4、MSDTC组件设置:

                  一般情况下只要你使用"TransactionScope",都要配置MSDTC,要配防火墙,要开139端口,这个端口不可以更改。

                  • 如果WEB服务器和数据库是在同一台服务器上,TransactionScope使用的是本地事务,这时不需要配置MSDTC。
                  • 如果WEB服务器和数据库不在同一台服务器上,TransactionScope会自动提升事务级别为分布式事务,这时就需要配置MSDTC。

                  对MSDTC组件设置:控制面板--->管理工具--->服务 中,开启Distributed Transaction Coordinator 服务。

                  • 控制面板->管理工具->组件服务->计算机->我的电脑->右键->属性,选择MSDTC页, 确认"使用本地协调器"。
                  • 点击下方"安全配置"按钮
                  • 勾选: "允许网络DTC访问","允许远程客户端","允许入站","允许出站","不要求进行身份验证".
                  • 对于数据库服务器端, 可选择"要求对呼叫方验证"
                  • 勾选:"启用事务Internet协议(TIP)事务"。
                  • 在双方防火墙中增加MSDTC.exe例外
                    可用命令行: netsh firewall set allowedprogram %windir%/system32/msdtc.exe MSDTC enable

                  八、依赖事务DependentTransaction,跨多个线程调用事务(显式事务)

                  一个环境事务绑定到一个线程上,如果新建了一个线程它就不会有第一个线程中的环境事务,两个线程中的事务完全独立。

                  如果多个线程使用同一个环境事务,需要给新线程传递一个依赖事务,调用Transaction的DependentClone方法创建依赖事务。

                  依赖事务通过DependentTransaction类型表示,和CommittableTransaction一样,DependentTransaction也是Transaction的子类。

                  DependentTransaction依赖于现有的Transaction对象而存在,相当于被依赖事务的子事务,具有一个唯一的方法成员:Complete。调用这个方法意味着向被依赖事务发送通知,表明所有与依赖事务相关的操作已经完成。

                  DependentClone方法具有一个DependentCloneOption枚举类型的参数:

                  • BlockCommitUntilComplete:表示被依赖事务在提交前会一直等待接收到依赖事务(子事务)的通知(调用Complete或者Rollback方法)或者超过事务设定的超时时限;
                  • RollbackIfNotComplete:如果被依赖事务在依赖事务(子事务)之前先完成,直接将被依赖的事务回滚,并抛出TransactionAbortedException异常。

                  下面的代码示例演示如何创建一个依赖事务来管理两个并发任务,具体为克隆一个依赖的事务并将其传递给辅助线程。

                  void Main() { using (TransactionScope scope = new TransactionScope()) { DependentTransaction dTx = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete); Thread thread = new Thread(ThreadMethod); thread.Start(dTx); /* Do some transactional work here, then: */ scope.Complete(); } } public void ThreadMethod(object transaction) { DependentTransaction dTx = transaction as DependentTransaction; try { //将DependentTransaction对象作为TransactionScope的参数,以初始化环境事务 using (TransactionScope ts = new TransactionScope(dTx)) { /* Perform transactional work here */ ts.Complete();//完成环境事务 } } finally { dTx.Complete();//完成依赖事务 dTx.Dispose(); } }

                  到此这篇关于c#事务的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持自由互联。