事务处理

第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,一经查实,立即删除!

相关文章

工作382-vant弹框不能直接用

this.$toast.success("当前所填项不能为空")

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

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

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

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

学习,学习javascript

学习javascript,时常看看这个朋友的博客:http://hi.baidu.com/mataofq/blog/category/Javascripthttp://www.zzsky.cn/build/content/543.htmhttp://www.zzsky.cn/build/content/1213.htm 转载于:https://www.cnblogs.com/xinzhuangzi/archive/2009/09/30/4100668.h…

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

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

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

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

课堂练习-水帖之王(水王)

今天的课堂练习是关于众数的查找。但是在这个枯燥的算法上,老师提出了一个很有意思而且很贴近我们日常上网生活的情景:有一个网友,他在一个吧里发帖数最多,而且占到了一半以上, 现在给出所有的帖子以及帖主的姓名&…

group by 与 order by

group by 1.对重复的数据合并分组,(group by a,b a列和b列的行数据相等才会合并)2.分组筛选(having\聚合函数)3.对各分组数据进行统计(聚合函数) order by order by a,b (先按a排序再按b排序)转载于:https://www.cnblogs.com/Ewin/archive/2009/10/05/1578293.html

只腐蚀毛刺 腐蚀算法_图像的腐蚀 膨胀及细化

转载:http://blog.sina.com.cn/s/blog_4bdb170b0100sgtj.html今天所讲的内容属于一门新兴的学科:数学形态学(Mathematical Morphology)。说起来很有意思,它是法国和德国的科学家在研究岩石结构时建立的一门学科。形态学的用途主要是获取物体拓…

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

原标题:计算机考研|这两所自划线,单科没过线也能复试?东南、浙大!单科没过线也能复试!关注量子考研公众号,获取最新计算机考研咨询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…

Python 各种应用收集

--共享文件的web server把文件放到一个目录中,使用终 端进入这个目录,输入python -m SimpleHTTPServer 8888。然后访问ip:8888。这个也 可以不过麻烦些:python -c "import SimpleHTTPServer ; SimpleHTTPServer.test()"转载于:http…

联想微型计算机M3500q怎么拆,联想ThinkCentre 超级Q 23 创新插拔 一机多用

继PC小型化、一体化风潮之后,联想再次取得突破性创新,为用户带来全球首创二合一可插拔一体机——ThinkCentre 超极Q 23继PC小型化、一体化风潮之后,联想再次取得突破性创新,为用户带来全球首创二合一可插拔一体机——ThinkCentre …

js正则匹配闭合标签_正则匹配闭合HTML标签(支持嵌套)

OK,先确定我们要解决的问题——从一段Html文本中找出特定id的标签的innerHTML。这里面最大的难点就是,Html标签是支持嵌套的,怎么能够找到指定标签相对应的闭合标签呢?我们可以这样想,先匹配最前面的起始标签&#xff…

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

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

Java基础之线程池

Java基础之线程池 转载于:https://www.cnblogs.com/daierge/p/10954228.html

工作387-vant控制日期范围

<van-cell-group><van-switch-cell size"26px" :active-value"active" active-color"#FFA9B5" inactive-color"#FFA9B5" v-model"checked" change"ChangeStatus" title"大姨妈来了" /><…

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

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

计算机硬件技术基础5章在线,《计算机硬件技术基础》试题(D)

有关《计算机硬件技术基础》,能够方便考生复习,保证不挂科。(D)一、单项选择题(每题1分&#xff0c;共20分)1、计算机的性能在很大程度上是由CPU决定的。CPU的性能主要体现为它的运算速度。下列有关计算机性能的叙述正确的是()。A、计算机中cache 存储器的有无和容量的大小对计…