我的编程空间,编程开发者的网络收藏夹
学习永远不晚

事务在c#中的使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

事务在c#中的使用

一、概述

1、事务ACID特性

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

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

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

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

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

二、数据库事务

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

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

  • 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);
        
        scope.Complete();
    }
}

public void ThreadMethod(object transaction)
{
    DependentTransaction dTx = transaction as DependentTransaction;
    try
    {
        //将DependentTransaction对象作为TransactionScope的参数,以初始化环境事务
        using (TransactionScope ts = new TransactionScope(dTx))
        {
            
            ts.Complete();//完成环境事务
        }
    }
    finally
    {
        dTx.Complete();//完成依赖事务
        dTx.Dispose();
    }
}

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

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

事务在c#中的使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何在 Golang 中使用事务?

在 go 中,可以使用 tx 类型进行事务操作。要开启事务,请使用 db.begin()。在事务块中,执行数据库操作,如查询、更新。执行成功后,使用 tx.commit() 提交事务。在实战中,事务可确保并发操作的一致性,如同时更新库存和创
如何在 Golang 中使用事务?
2024-05-14

事务如何在Spring Boot 中使用

今天就跟大家聊聊有关事务如何在Spring Boot 中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。spring Boot 使用事务非常简单,首先使用注解 @EnableTra
2023-05-31

如何在java中使用JDBC事务

今天就跟大家聊聊有关如何在java中使用JDBC事务,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代
2023-06-14

在不同的 DAO 中使用相同的 DB 事务

本篇文章给大家分享《在不同的 DAO 中使用相同的 DB 事务》,覆盖了Golang的常见基础知识,其实一个语言的全部知识点一篇文章是不可能说完的,但希望通过这些问题,让读者对自己的掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的
在不同的 DAO 中使用相同的 DB 事务
2024-04-04

django中使用mysql的事务

事务简介  在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。  事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。  事务用来管理 insert,update,delete 语句  一般来说
django中使用mysql的事务
2019-06-17

如何在java中使用Connection管理事务

本篇文章给大家分享的是有关如何在java中使用Connection管理事务,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。Java的优点是什么1. 简单,只需理解基本的概念,就可
2023-06-14

怎么在Django中使用transaction管理事务

本篇文章给大家分享的是有关怎么在Django中使用transaction管理事务,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。1. transaction事务内不执行数据库的c
2023-06-14

在Laravel中如何使用数据库事务

小编给大家分享一下在Laravel中如何使用数据库事务,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!什么是数据库事务?在我们开始研究 Laravel 的数据库事务之前,让我们先看看它们是什么以及它们如何有益。对于什么是数据
2023-06-22

C/C++开发中extern的一些使用注意事项

这篇文章主要为大家介绍了C/C++开发中extern一些使用注意事项的事例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-04

Hyperledger Fabric 使用 go sdk 在 CouchDB 中存储事务

小伙伴们对Golang编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《Hyperledger Fabric 使用 go sdk 在 CouchDB 中存储事务》,就很适合你,本篇文章讲解的知识点主要包括。在之后的文章中也会多多分享相
Hyperledger Fabric 使用 go sdk 在 CouchDB 中存储事务
2024-04-05

ThinkPHP中的事务怎么使用

今天小编给大家分享一下ThinkPHP中的事务怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、事务的概念事务是一系
2023-07-05

C#的button事件怎么使用

本篇内容介绍了“C#的button事件怎么使用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!C# button事件说明:splitConta
2023-06-17

详解在Spring Boot中使用数据库事务

我们在前面已经分别介绍了如何在spring Boot中使用JPA以及如何在Spring Boot中输出REST资源。那么关于数据库访问还有一个核心操作那就是事务的处理了,前面两篇博客小伙伴们已经见识到Spring Boot带给我们的巨大便利
2023-05-31

C#中怎么使用委托和事件

在 C# 中,委托和事件是一种常用的机制,用于实现事件驱动的编程模型。委托是一种类型,用于存储对方法的引用,而事件是委托的一种特殊用法,用于通知其他代码发生了某个特定的动作。下面是一个简单的示例,演示了如何在 C# 中定义和使用委托和事件
C#中怎么使用委托和事件
2024-03-06

怎么在Java中使用NIO的Write事件

这期内容当中小编将会给大家带来有关怎么在Java中使用NIO的Write事件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。一、NIO Server端1.1 多路复用开发一般步骤//打开选择器Selecto
2023-06-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录