事务处理

第13章 事务处理

事务处理是包含一个或多个任务的一组关联操作的提交或回滚操作。在事务执行的过程中,保证事务具有基本的ACID属性(原子、一致性、隔离和持久性)。.NET Framework的事务管理支持多种事务处理方式,包括显性事务和隐性事务、本地事务和分布式事务、事务嵌套、事务升级等,同时包含了三种主要信任级别:AllowPartiallyTrustedCallers(APTCA)信任级别、DistributedTransactionPermission(DTP)信任级别和完全信任级别。要使用事务处理应在程序头部引用System.Transactions命名空间。

13.1  使用SqlTransaction实现数据库操作事务

SqlTransaction类是对SQL Server数据库进行事务处理的类,该类的实例由SqlConnection类实例的BeginTransaction方法创建,表示在该数据库连接实例上开始一个数据库事务,创建SqlTransaction类实例后,在程序中使用该实例的Commit方法提交事务,或者使用该类的Rollback方法回滚事务。

技术要点

本示例主要说明了如何在程序中使用SqlTransaction实现数据库操作事务,技术要点如下。
 
SqlTransaction类实例由SqlConnection类实例的BeginTransaction方法创建,表示将在该数据库连接实例上开始一个数据库操作事务。
 
数据库连接作为事务范围时,当事务范围结束数据库连接将会自动关闭。
 
创建操作数据库的SqlCommand类实例时,必须使用数据库连接和数据库事务来创建,该数据库命令实例才能在事务中登记,才能使该命令的执行纳入事务处理的范围内。

实现步骤

(1)创建控制台应用程序项目,命名为“DatabaseSqlTransaction”。

(2)打开并编辑Program.cs文件,代码如下所示。

 using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace DatabaseSqlTransaction
{
class Program
{
static void Main(string[] args)
{
//连接数据库的字符串
string ConnectionString = @"Data Source = localhost;
Initial Catalog = Northwind; Integrated Security = SSPI;";
//使用数据库连接作为事务范围
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
conn.Open();//连接数据库
SqlTransaction transaction;
//开始一个本地事务
transaction = conn.BeginTransaction("MyTransaction");
//必须为SqlCommand指定数据库连接和登记的事务
SqlCommand cmd = new SqlCommand("", conn, transaction);
try
{
//向数据表中插入记录的命令语句
cmd.CommandText = @"Insert into Region (RegionID,
RegionDescription)
VALUES (10, '自定义描述A')";
cmd.ExecuteNonQuery();
cmd.CommandText = @"Insert into Region (RegionID,
RegionDescription)
VALUES (11, '自定义描述B')";
cmd.ExecuteNonQuery();
transaction.Commit();//提交事务
Console.WriteLine("操作完成");
}
catch (Exception ex)
{
Console.WriteLine("提交错误类型: {0}", ex.GetType());
Console.WriteLine("提交错误信息: {0}", ex.Message);
try
{
transaction.Rollback();//回滚事务
}
catch (Exception ex2)
{
Console.WriteLine("回滚错误类型: {0}", ex2.GetType());
Console.WriteLine("回滚错误信息: {0}", ex2.Message);
}
}
}
Console.ReadLine();
}
}
}
(3)按F5键运行程序,运行结果如下所示。
 操作完成
(4)按下回车键结束程序运行,再次按下F5键运行程序,运行结果如下所示。
提交错误类型: System.Data.SqlClient.SqlException
提交错误信息: 违反了 PRIMARY KEY 约束 'PK_Region'。不能在对象 'Region' 中插入重
复键。
语句已终止。

源程序解读

(1)本示例程序创建一个SqlConnection类的实例,并将该实例作为事务范围,在该范围内使用SqlConnection类实例创建一个SqlTransaction类实例的本地事务,使用数据库连接类实例和数据库事务类实例,创建一个SqlCommand类的实例,并为该SqlCommand类实例指定数据库操作命令,执行该操作如果执行过程正常,则提交事务,否则,将数据库操作事务回滚。本示例程序的流程图如图13.1所示。

 
图13.1  使用SqlTransaction实现数
据库操作事务示例程序流程图

(2)在本示例中使用了信任连接字符串连接SQL Server数据库,在数据库连接包含的事务范围结束时会自动关闭数据库连接,不需要编写关闭数据库连接的代码。



13.2  使用TransactionScopeOption实现事务选项控制

TransactionScopeOption枚举是创建事务范围的重要选项,该枚举中包含三个成员,其中Required成员表示创建的范围需要一个事务,如果已经存在外部的事务,就使用外部事务作为当前的事务,如果不存在外部事务,就创建一个新的事务,在事务范围的构造函数中,如果没有指定TransactionScopeOption枚举的参数,默认使用Required创建事务范围。RequiresNew成员表示为当前范围创建一个新的事务,而无论是否存在外部事务。Suppress成员表示取消当前范围的外部事务,范围内的所有操作在事务外部执行。

技术要点

本示例主要说明了如何在程序中使用TransactionScopeOption实现事务选项控制,技术要点如下。
 
使用RequiresNew成员创建的事务范围时,即使存在外部事务,当前范围也将创建新的事务,这样当前事务范围在调用Complete方法结束事务范围的时候,就执行了提交动作,而不是等到外部事务调用Complete方法时才进行提交。
 
使用Required成员创建的事务范围时,如果存在外部事务,就使用外部事务,这样当前事务范围在调用Complete方法结束事务范围的时候,实际上并不能进行执行提交动作。只有当外部的事务范围调用Complete方法结束时,才能执行提交动作。

实现步骤

(1)创建控制台应用程序项目,命名为“ControlTransactionScopeOption”。

(2)打开并编辑Program.cs文件,代码如下所示。

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
using System.Transactions;
namespace ControlTransactionScopeOption
{
class Program
{
static void Main(string[] args)
{
//使用事务范围ts1
using (TransactionScope ts1 = new TransactionScope())
{
//连接数据库的字符串1
string ConnectionString1 = @"Data Source = localhost;
Initial Catalog = Northwind; Integrated Security = SSPI;";
//使用RequiresNew参数创建ts1的子事务subts1
using (TransactionScope subts1 = new TransactionScope
(TransactionScopeOption.RequiresNew))
{
//创建数据库连接类实例1
SqlConnection conn1 = new SqlConnection(ConnectionString1);
//将在数据库连接实例1上执行的命令
SqlCommand command1 = new SqlCommand(@"INSERT Shippers
(CompanyName, Phone) VALUES('Test Ship1','0000-0001')", conn1);
conn1.Open();
command1.ExecuteNonQuery();//执行数据库操作
conn1.Close();
subts1.Complete();//完成子事务1
}
//连接数据库的字符串2
string ConnectionString2 = @"Data Source = localhost;
Initial Catalog = Northwind; Integrated Security = SSPI;";
//使用Required参数创建ts1的子事务subts2
using (TransactionScope subts2 =new TransactionScope
(TransactionScopeOption.Required))
{
//创建数据库连接类实例2
SqlConnection conn2 = new SqlConnection(ConnectionString2);
//将在数据库连接实例2上执行的命令
SqlCommand command = new SqlCommand(@"INSERT Shippers
(CompanyName,Phone) VALUES('Test Ship2','0000-0002')",conn2);
conn2.Open();
command.ExecuteNonQuery();//执行数据库操作
conn2.Close();
subts2.Complete();//完成子事务
}
//完成ts1事务的语句,去掉注释后subts2的事务才能提交
//ts1.Complete();
//连接数据库的字符串3
string ConnectionString3 = @"Data Source = localhost;
Initial Catalog = Northwind; Integrated Security = SSPI;";
//创建数据库连接类实例3
SqlConnection conn3 = new SqlConnection(ConnectionString3);
//打开数据库连接
conn3.Open();
//读取数据库中Shippers表的数据
SqlDataReader dr = new SqlCommand("SELECT *
FROM Shippers", conn3).ExecuteReader();
while (dr.Read()) //循环显示数据
{
Console.WriteLine("{0} {1} {2}",
dr.GetInt32(0).ToString(),
dr.GetString(1),
dr.GetString(2));
}
dr.Close();//关闭SqlDataReader类实例
conn3.Close();//关闭数据库连接类实例
Console.ReadLine();
}
}
}
}

(3)按F5键运行程序,运行结果如下所示。
1 Speedy Express (503) 555-9831
2 United Package (503) 555-3199
3 Federal Shipping (503) 555-9931
4 Test Ship1 0000-0001

源程序解读

(1)本示例程序定义了一个外部的事务范围ts1,在该范围内分别使用TransactionScopeOption枚举的RequiresNew成员和Required成员创建了两个事务范围。在这两个事务范围内,分别创建数据库连接,并执行SQL命令语句。然后在事务范围之外,查询并显示数据库中的表记录,以检查事务的提交情况。本示例程序的流程图如图13.2所示。

  
图13.2  使用TransactionScopeOption实现事务选项控制的示例程序流程图


(2)根据程序运行结果显示,使用Required成员创建的事务范围中的操作未被提交,原因是Required成员创建的事务范围使用的是外部事务,在外部事务未提交时当前事务范围中的所有数据操作均未提交。

(3)除去本示例程序注释的外部事务范围ts1的调用Complete方法语句,将结束ts1事务,并将该事务范围内的所有数据操作提交,此时将提交Required成员创建的事务范围内的数据操作。


 

13.3  使用TransactionScope实现单数据库连接事务操作

TransactionScope类表示一个事务范围,位于该范围内的代码块都成为一个事务,在调用TransactionScope类中定义的Complete方法时将结束并提交事务。

技术要点

本示例主要说明了如何在程序中使用TransactionScope实现单数据库连接的事务操作,技术要点如下。
 
在TransactionScope类实例表示的事务范围中,所有的数据库操作代码都将作为一个事务执行,只有在调用该事务范围实例的Complete方法时,才提交对数据库的操作。
 
当事务范围中的数据库操作失败时,事务范围自动回滚数据库操作。

实现步骤

(1)创建控制台应用程序项目,命名为“SingleDatabaseTransactionScope”。

(2)打开并编辑Program.cs文件,代码如下所示。

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using System.Data;
using System.Data.SqlClient;
namespace SingleDatabaseTransactionScope
{
class Program
{
static void Main(string[] args)
{
//在创建的事务范围实例内运行代码
using (TransactionScope ts = new TransactionScope())
{
//连接数据库的字符串
string ConnectionString = @"Data Source =
localhost; Initial Catalog = Northwind; Integrated Security = SSPI;";
//创建数据库连接类实例
SqlConnection conn = new SqlConnection(ConnectionString);
//创建三个数据库SqlCommand命令类实例
SqlCommand command1 = new SqlCommand
(@"DELETE FROM Shippers WHERE CompanyName LIKE 'Test Ship%'", conn);
SqlCommand command2 = new SqlCommand
(@"INSERT Shippers(CompanyName,Phone) VALUES('Test Ship1','0000-0001')", conn);
SqlCommand command3 = new SqlCommand
(@"INSERT Shippers(CompanyName,Phone) VALUES('Test Ship2','0000-0002')", conn);
try
{
conn.Open();//打开数据库
command1.ExecuteNonQuery();//执行查询
Console.WriteLine("第一个命令执行成功");
command2.ExecuteNonQuery();
Console.WriteLine("第二个命令执行成功");
command3.ExecuteNonQuery();
Console.WriteLine("第三个命令执行成功");
}
finally
{
if (conn.State == ConnectionState.Open)
{
conn.Close();//关闭数据库
}
}
Console.Write("是否提交事务?(Y/N)");
if (Console.ReadKey(false).Key== ConsoleKey.Y)
{
ts.Complete();//结束事务,提交数据库执行的命令
Console.WriteLine("");
Console.WriteLine("提交事务完毕");
}
else
{
Console.WriteLine("");
Console.WriteLine("取消事务提交");               
}
Console.ReadLine();
}
}
}
}
(3)按F5键运行程序,运行结果如下所示。
第一个命令执行成功
第二个命令执行成功
第三个命令执行成功
是否提交事务?(Y/N)y
提交事务完毕

源程序解读

(1)本示例程序创建一个事务范围,在该事务范围内创建数据库连接,并在该数据库连接上创建三个SqlCommand类的实例,执行这三个数据库命令,最后根据用户通过键盘输入决定是否提交事务。本示例程序的流程图如图13.3所示。

  
图13.3  使用事务范围实现单数据
库连接事务操作的示例程序流程图

(2)使用TransactionScope类示例创建事务范围实现事务处理的方式,称为隐式事务编程模型。在该模型中,事务的基本的ACID属性(原子、一致性、隔离和持久性),由该类的基础结构实现、事务的提交和回滚实际上都在基础结构中完成,该类中定义的Complete方法实际上仅仅是通知基础结构当前事务代码已经完成可以开始提交。


13.4  使用TransactionScope实现多数据库连接事务操作

当应用程序需要在多个数据库中进行事务性操作的时候,使用TransactionScope类可以方便地实现应用程序的这一需求。只要对多个数据库的操作代码位于同一个事务范围内,即可实现多数据库连接的事务操作。

技术要点


本示例主要说明了如何在程序中使用TransactionScope实现多数据库连接事务操作,技术要点如下。
 
因为位于同一个事务范围内的不同的数据库操作,程序视为同一个事务,所以使用事务范围能够简便地实现多数据连接的事务操作。
 
在事务范围内应调用且仅仅调用一次Complete方法,当事务范围的Complete方法调用时,事务范围中的数据操作尝试提交,提交失败时自动回滚,如果在事务范围内未执行Complete方法,则导致事务范围在操作未提交的情况下结束。

实现步骤

(1)创建控制台应用程序项目,命名为“MultiDatabaseTransactionScope”。

(2)打开并编辑Program.cs文件,代码如下所示。

 

using System;
using System.Collections.Generic;
using System.Text;
using System.Transactions;
using System.Data;
using System.Data.SqlClient;
namespace MultiDatabaseTransactionScope
{
class Program
{
static void Main(string[] args)
{
//在创建的事务范围实例内运行代码
using (TransactionScope ts = new TransactionScope())
{
//连接数据库1的字符串
string ConnectionString1 = @"Data Source =
localhost; Initial Catalog = Northwind; Integrated Security = SSPI;";
//创建数据库1连接类实例1
SqlConnection conn1 = new SqlConnection(ConnectionString1);
//创建数据库1命令类实例1
SqlCommand command1 = new SqlCommand(@"INSERT
Shippers(CompanyName,Phone)
VALUES('Test Ship2','0000-0002')", conn1);
conn1.Open();//连接数据库1
command1.ExecuteNonQuery();//在数据库1上执行命令
Console.WriteLine("数据库1的命令已执行");
conn1.Close();//关闭数据库1
//连接数据库2的字符串
string ConnectionString2 = @"Data Source =
localhost; Initial Catalog = pubs; Integrated Security = SSPI;";
//创建数据库2连接类实例2
SqlConnection conn2 = new SqlConnection(ConnectionString2);
//创建数据库2命令类实例2
SqlCommand command2 = new SqlCommand(@"INSERT
Discounts(Discounttype,Discount) VALUES('Other',12)", conn2);
conn2.Open();//连接数据库2
command2.ExecuteNonQuery();//在数据库2上执行命令
Console.WriteLine("数据库2的命令已执行");
conn2.Close();//关闭数据库2
Console.Write("是否提交事务?(Y/N)");
if (Console.ReadKey(false).Key == ConsoleKey.Y)
{
ts.Complete();//提交事务
Console.WriteLine("");
Console.WriteLine("事务提交完成");
}
else
{
Console.WriteLine("取消事务提交");
}
}
}
}
}

(3)按F5键运行程序,运行结果如下所示。
数据库1的命令已执行
数据库2的命令已执行
是否提交事务?(Y/N)y
事务提交完成

源程序解读

本示例程序创建了一个事务范围,并在该事务范围内创建两个不同的数据库连接,并通过SqlCommand类实例执行数据操作,最后通过用户的键盘输入决定是否提交两个数据库连接中的数据操作事务。本示例程序的流程图如图13.4所示。

  
图13.4  使用事务范围实现多数据
库连接事务操作的示例程序流程图

转载于:https://www.cnblogs.com/HughTan/archive/2009/09/28/1575657.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/411267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

为多孔介质的当量直径_多孔介质流建模简介

拥有一款先进的多孔介质建模工具,是许多行业的刚性需求。COMSOL Multiphysics 软件 5.5 版本新增的附加产品——多孔介质流模块,可以满足众多行业的需求。使用该模块可以定量研究多孔介质中的质量、动量和能量传递。该模块适用于燃料电池、纸浆和纸张干燥…

北航计算机网络 传输层实验,北航研究生计算机网络实验_实验七 传输层实验

** 这个实验我没有约到没有问题的机子(连续三台机子都是坏的...)因此仅供参考1、根据2.6中步骤3回答:TCP的连接和建立采用的是:三次握手方式,PCA是主动打开方(C),PCB是被动打开方(S)。先点击发送再点击接收,会出现什么…

python 竖线 绘图_Python可视化 | Seaborn5分钟入门(二)——barplot countplot

Seaborn是基于matplotlib的Python可视化库。 它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matplotlib的基础上进行了更高级的API封装,从而使得作图更加容易,不需要经过大量的调整就能使你的图变得精致。注:所有代码均在IP…

计算机网络工程综合布线目的,弱电工程综合布线系统与计算机网络布线系统有何不同?【网络综合布线】...

弱电工程的综合布线是模块化和灵活的建筑物或建筑物之间的信息传输通道。 综合配电系统可以连接到声音设备、数据设备、开关设备和各种控制设备和信息管理系统。 同时,它还使这些设备与外部通信网络连接起来。弱电工程综合布线系统与计算机网络布线系统有何不同..弱…

计算机专硕专业课单科分数线,计算机考研|这两所自划线,单科没过线也能复试?...

原标题:计算机考研|这两所自划线,单科没过线也能复试?东南、浙大!单科没过线也能复试!关注量子考研公众号,获取最新计算机考研咨询1.东南大学:统考考生(不含报考苏州联合研究生院考生和管理类联…

Saltstack_使用指南17_salt-ssh

1. 主机规划 salt 版本 1 [rootsalt100 ~]# salt --version 2 salt 2018.3.3 (Oxygen) 3 [rootsalt100 ~]# salt-minion --version 4 salt-minion 2018.3.3 (Oxygen) salt ssh文档 https://docs.saltstack.com/en/latest/topics/ssh/index.html 2. salt-ssh实现步骤 2.1. 部署s…

新手入门:AIX操作系统安装图解

AIX(Advanced Interactive Executive)是IBM 公司的UNIX操作系统,它特别适合于做关键数据处理。2002年IBM发布了AIX 5.2版。 下面就以该版本为例来介绍IBM的AIX操作系统的安装,主要介绍在IBM P630机器上如何使用AIX软件的光盘&…

华为荣耀9x怎么解账户锁_麒麟820,4000万像素,荣耀X10是下一部千元街机?

哈喽黑粉们,欢迎来到黑马公社。最近发布的新机很多,其中之一就是黑马此前和大家聊过多次的荣耀X10。这款新机于昨天5月20日发布,表现怎么样呢?今天黑马就来聊聊这款新机。和此前爆料的一样,荣耀X10采用了升降式设计&am…

关键词提取算法

1、先给本聚类内的所有文档进行分词,然后用一个字典保存每个词出现的次数;2、遍历每个词,得到每个词在所有文档里的IDF值,和在本聚类内出现的次数(TF)相乘的值;3、用一个字典(key是词,value是TF*IDF权重)来…

JavaWeb的分页

1.什么是分页 第N页/共M页 首页 上一页 1 2 3 4 5 6 7 8 9 下一页 尾页 [ ] go 分页的优点:只查询一页,不用查询所有页! 2.分页数据 页面的数据都是由Servlet传递过来的! Servlet: 1.*当前页:pageCod…

中反应器体积_缠绕管式反应器大幅提高能效,移热能力较列管式反应器提升逾50%...

武汉东海石化重型装备有限公司与中科院过程工程研究所联合开展的高效缠绕管式反应器研发课题二期研究日前结题。该研究建立了一套与不同工作原理相适应的缠绕管式反应器设计方法,使缠绕管式反应器的移热能力较列管式固定床反应器提升逾50%,可极大提高企业…

【异常(待解决)】org.apache.http.NoHttpResponseException: api.weixin.qq.com:443 failed to respond...

一、记录下异常堆栈信息 2019-06-01 10:26:58.246 [http-nio-9850-exec-3] ERROR weixin.popular.client.LocalHttpClient - execute error org.apache.http.NoHttpResponseException: api.weixin.qq.com:443 failed to respondat org.apache.http.impl.conn.DefaultHttpRespon…

企业内容管理-互联网应用

企业内容管理-互联网应用 当你第一次听到企业内容管理这个名字,很容易联想到ERP这种复杂无比的系统。实际上也确实如此,目前几大主要的ECM系统都是复杂无比,所以我想从互联网应用,一般网民可以使用的角度来谈谈企业内容管理。 从…

计算机做游戏到大学要学什么,大学学什么专业,毕业才能从事电竞行业?

原标题:大学学什么专业,毕业才能从事电竞行业?电竞可不只是打游戏这么简单。想必最近很多同学已经陆陆续续收到录取通知书了,大学的美好生活已经在等着你们啦!今天化学姐想和大家聊聊就业已经游戏行业相关的事儿。电子…

layui中table监听单元格_最全总结 | 聊聊 Python 办公自动化之 PPT(中)

点击上方 “AirPython”,选择 “加为星标”第一时间关注 Python 技术干货!1. 前言上一篇文章简单地介绍了 PPT 的文档结构,并使用 python-pptx 这个依赖库完成对 PPT 文档最基本的操作最全总结 | 聊聊 Python 办公自动化之 PPT(上)作为 PPT 系…

东北考生到南方学计算机,为啥东北考生都想去南方,而南方学生很少考东北,看看他们怎么说...

原标题:为啥东北考生都想去南方,而南方学生很少考东北,看看他们怎么说文/晓宁说教育高考对于众多考生来说,是人生中最重要的一场考试,如果能在高考中发挥出好成绩,就可以顺利的考上一所自己理想的大学。按照…

用excel制作双层饼图_双层饼图,让你的工作更出彩

在Excel中饼图是很常见的图表类型,做起来也很简单,相信大家都会做。但双层饼图你会做吗?如下图所示,根据左侧的数据源,做出右侧的双层饼图。这么漂亮的双层饼图是怎么制做出来的呢?今天我就来给大家分享一下…

Comet OJ - 2019 六一欢乐赛

传送门 #A&#xff1a; 思路&#xff1a;等差数列求和,看成俩次12… n,多加的n减去&#xff0c;所以 ans n*(n1) - n。 AC代码&#xff1a; 1 #include<iostream>2 #include<algorithm>3 #include<string>4 using namespace std;5 int main()6 {7 int n…

三个子系统_「正点原子Linux连载」第五十八章Linux INPUT子系统实验(一)

1)实验平台&#xff1a;正点原子Linux开发板2)摘自《正点原子I.MX6U嵌入式Linux驱动开发指南》关注官方微信号公众号&#xff0c;获取更多资料&#xff1a;正点原子第五十八章Linux INPUT子系统实按键、鼠标、键盘、触摸屏等都属于输入(input)设备&#xff0c;Linux内核为此专门…

【翻译】eXpressAppFramework QuickStart 业务模型设计(十)——在代码中实现数据验证...

这一讲&#xff0c;你将学到如何给业务对象和他们的属性设置规则。最终用户在执行赋值操作后将验证这些规则。你可以实现必填规则使得Position.Title属性不能为空。此规则将在Position对象保存的时候被验证。你还能够看到打破规则的界面提示。在此之前&#xff0c;我建议你去读…