transactionscope spring scope默认值什么级别

一、什么是TransactionScope?
  TransactionScope即范围事务(类似数据库中的事务),保证事务声明范围内的一切数据修改操作状态一致性,要么全部成功,要么全部失败回滚.
  MSDN:如果在事务范围内未不发生任何异常 (即之间的初始化 TransactionScope 对象并调用其 Dispose 方法),则范围所参与的事务可以继续,否则参与到其中的事务将回滚。      当应用程序完成所有工作时它想要在事务中执行,应调用 Complete 方法一次,以通知该事务管理器是可接受(此时事务并未提交),即可提交事务,未能调用此方法中止事务。      调用 Dispose 方法将标记事务范围的末尾。 在调用此方法之后所发生的异常不会影响事务。
二、TransactionScope有什么用?
  假如现在有一个需求:实现一个下单功能,主要业务包含扣减商品库存、扣减用户账户余额、生成订单记录以及记录日志。为了保证数据一致性我们通常的做法就是在数据库建一个下订单的事务,然后程序调用事务传入相应的参数即可。那么问题来了,如果用户的账户数据跟订单数据分别处于不同的数据库,就没法在同一个数据库事务里完成所有任务,也就没法保证数据的一致性。  最近由于业务的变更公司改用MySQL数据库,处理数据变更时习惯性先写事务,写的时候发现现有数据库中一个事务都没有,于是去问java组,不使用事务怎么保证数据的一致性?得到的答复是:事务是什么鬼,spring帮我们解决所有问题...。立马就懵逼了,.net中没听说有Spring啊(据说有类似的框架),虽然可以考虑使用仓储加工作单元来解决,但是感觉好麻烦的样子,后来寻找解决方案时发现了TransactionScope。
三、TransactionScope怎么使用?
using (TransactionScope scope = new TransactionScope())
//TODO:数据处理业务
9 catch (Exception ex)
四、问题探讨
1、准备工作
1 //数据库访问对象
2 public class Studuent
public static IList&StudentModel& GetList()
//不允许脏读
string sql = "SELECT Id,Name,CreateTime FROM Student ORDER BY Id DESC;";
DataTable dt = SQLHelper.ExecuteDataTable(CommandType.Text, sql);
return dt.ToModel&StudentModel&();
public static bool Add(string name)
SqlParameter[] parms = { new SqlParameter("@Name", SqlDbType.NVarChar, 32) { Value = name } };
string sql = "INSERT INTO Student (Name) VALUES (@Name)";
return SQLHelper.ExecuteNonQuery(CommandType.Text, sql, parms) & 0;
public static void Clear()
SQLHelper.ExecuteNonQuery("DELETE Student");
1 //公共方法,输出学生列表
2 static void PrintStudent()
IList&StudentModel& list = Studuent.GetList();
foreach (var item in list)
Console.WriteLine("{0}\t{1}\t{2}", Thread.CurrentThread.ManagedThreadId, item.Name, item.CreateTime);
Console.WriteLine();
2、事务什么时候提交?
最初我以为在执行Complete后即刻提交,但根据输出结果可以看出,Complete方法执行两秒之后事务依旧没有提交。因为不允许脏读的原因,主线程会在事务对Student表操作完成后才可查询完成,但学生列表是在scope调用dispose方法之后输出,MSDN介绍说dispose确定事务范围末尾,因此猜测事务是在调用dispose时被提交。
3、异常是怎么导致数据不被提交?
对比两幅图可以看出,异常在Complete之后发生并不会影响事务的提交,事务未提交是因为发生异常导致Complete未被执行。之前看过一篇文章说,如果TransactionScope范围中没有调用Complete会导致程序异常,我想他肯定是开玩笑的...
4、嵌套事务
阅读(...) 评论()文章分类文章档案友情链接1:本地事务DbTransaction和分布式事务TransactionScope的区别:
1.1:mon.DbTransaction:
本地事务:这个没什么好说了,就是单个事务,每种数据库都有自己的实现,事务的深度内涵可以搜索查看相关的文章,不是本文介绍的重点。
1.2:System.Transactions.TransactionScope:
分布式事务,需要添加引用System.Transactions,同时启用MSDTC分布式事务服务:通常使用方式为:
&using&(System.Transactions.TransactionScope&ts&=&new&System.Transactions.TransactionScope())
&&&&&&&&&&&&&&&&//代码块A
&&&&&&&&&&&&&&&&//代码块B
&&&&&&&&&&&&&&&&plete();//提交事务
分布式事务本质上是引入了第三方裁判,来想办法对多个本地事务监控同时成功或同时失败,这里分享几个知识点:
A:如果代码块里,若存在两个或以上数据库链接DbConnection,则需要启动微软的MSDTC分布式事务服务。
用命令行启动或停止服务:
B:如果代码块里,只有一个数据库链接DbConnection,那么实际上只是本地事务在处理,就算MSDTC分布式事务服务没启动,也不会报错。
C:对于TransactionScope包含的代码块,本质是监控了代码块里数据库链接DbConnection的个数,如果有多个不同的对象,则引入MSDTC当裁判,而实际执行的事务的还是各个本地事务。
D:MSDTC总是不够稳定,我在测试时两个简单的事务一起时,按住F5不停刷新,竟然能把MSSQL服务也给挂了,而用本地事务就算跨库也不会有问题。
所以,不是必须的情况,尽量不要引入分布式事务,应该避免使用TransactionScope来包含事务块的冲动。&
2:可以用本地事务解决,避免使用分布式事务场景:
2.1:项目只有一个数据库,这个是最应该避免,多个表间的事务, 完全是本地事务可处理的范围:
问题:一个代码块里N个实体类杂交操作,每个实体类带有各种的数据库链接,从而引发了MSDTC。
可以:共用一个DbConnection对象,来避免启用MSDTC。
2.2:项目多个数据库,如果数据库间使用了相同的访问账号和密码,这种情况也可以避免:
每种数据库有自己的解决方式:像MSSQL,跨库处理只要加前缀(dbname..tablename)就可以,因此也使的只使用本地事务就可以处理了。
3:回顾下我以前的项目场景:
3.1:从下图是我08年在中域的项目:有19个数据库,对于数据库链接而言,唯一的不同只有数据库的名称:
进化:能不能只保留一条,其它的通过动态切换数据库名称来改链接字符串?
3.2:那时候,我的架构还是很新手,通过CodeSmith生成了大量的代码文件:
实体类项目,工厂项目,接口项目,数据操作,还有大量的增删改查存储过程,只是为了基础的增删改查而且只针对MSSQL。
随便展开一个项目都会看到大量的文件夹,里面有大量的文件,而这些东东,都是代码生成器的杰作:
19个数据库啊,NN个表,光生成这些基本的增删改查,整个项目就好像高端大气上档次了。
进化:能不能消灭这些大量的文件,简单是我们不断追求的目标。
3.3:这么多数据库,如何跨数据库事务?
对于生成的大量的实体,每个表的操作都是一个新的链接,单库间的事务都必须MSDTC了,更别说19个库间的跨库事务了。
进化:能不能本地事务搞定这些,这是每个ORM可以思考的方向。
4:CYQ.Data 提供的解决方案:&
为了消灭上述的那些大量的生成文件,我在后续新的公司写了传统的ORM框架:XQData(这个框架一直没露过面,也只是支持MSSQL,用反射消灭了好多层,只留下实体层)。
对于框架的演进,多数都来源于项目中遇到的问题,或复杂的场景,需要解决或者简化,才有了不断升级的可能,并不是无中生有,因此,一个框架,如果不能不断在在项目中实战,那么很多问题和细节等可能都无法发现,更新也会遥遥无期。&
而CYQ.Data的不断升级,说明我一直在奋战在一线的编码生涯中和网友各大项目中的实战反馈中。&
下面针对最近的优化调整,演示下CYQ.Data是怎么解决上面提到的几个问题:
4.1:多个数据库的数据库链接切换:
A:先用配置工具生成针对多数据库的枚举文件,和成demo和test两个数据库:
两个数据库就生成两次了。
B:配置一个默认的链接字符串,到Demo数据库:
&add&name="Conn"&connectionString="server=.;database=uid=pwd=123456"/&
C:打印操作Test数据库表的链接字符串:
using&(MAction&action&=&new&MAction(TestEnum.Users))
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&Console.WriteLine(action.ConnectionString);
&&&&&&&&&&&&}
这里自动切换了数据为名称为新的链接,而我动手脚的地方就是在枚举的名称了。
4.2:本地多数据库跨事务,示例:
& & & & & & AppDebug.OpenDebugInfo&=&true;
&&&&&&&&&&&&AppDebug.Start();
&&&&&&&&&&&&using&(MAction&action&=&new&MAction(DemoEnum.Users))
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&action.BeginTransation();//开启事务
& & & & & & & & &action.Fill(12);
&&&&&&&&&&&&&&&&Console.WriteLine(action.ConnectionString);//打印数据库链接
&&&&&&&&&&&&&&&&action.ResetTable(TestEnum.Users);//切换数据库
&&&&&&&&&&&&&&&&Console.WriteLine(action.ConnectionString);//打印数据库链接
& & & & & & & & action.Fill(12);
&&&&&&&&&&&&&&&&action.EndTransation();
&&&&&&&&&&&&}
&&&&&&&&&&&&Console.);//输出所有执行的SQL语句。
&&&&&&&&&&&&AppDebug.Stop();
输出的结果:
说明:在事务中,当检测到事务开启时,为了使用本地事务,并没有切换数据库,而是采用了前缀来执行操作。
如果注释掉代码中的事务,则是直接切换数据库链接,输出会如下图:
说明:如果没有开启事务,则直接切换了数据库链接,并消消灭前缀语法。
对于.NET领域,微软除了提供这个不太稳定的MSDTC,似乎没有发现其它分布式事务的解决方案,好在一般的项目,我们在本地事务就可以处理。
希望微软可以在一些重点分布式上多做点研究、普及和推广,提供大型项目的解决方案,别整天操碎心在那些简单的增删改查上。
秋色园是QBlog的官方站点,由路过秋天创建,基于cyqdata数据层框架开发的支持多用户、多语言、多数据库(access,mssql,oracle)、目录级url等功能强大的博客系统"不错不错,后面的 AD 也显得很自然 让人心生喜欢 哈哈哈。ai commenc茅 脿 se engager dans la reddition de comptes, tout en leur donnant la promotion自由、创新、研究、探索
Linux/Windows Mono/DotNet [ Open Source .NET Development/ 使用开源工具进行DotNet软件开发]锐意进取,志存高远.成就梦想,只争朝夕.从你开始,创新世界.【That I exist is a perpetual supprise which is life. Focus on eCommerce】
最近在园子里看到一篇关于TransactionScope的文章,发现事务和并发控制是新接触Entity Framework和Transaction Scope的园友们不易理解的问题,遂组织此文跟大家共同探讨。
首先事务的ACID特性作为最基础的知识我想大家都应该知道了。ADO.NET的SQLTransaction就是.NET框架下访问SqlServer时最底层的数据库事务对象,它可以用来将多次的数据库访问封装为&原子操作&,也可以通过修改隔离级别来控制并发时的行为。TransactionScope则是为了在分布式数据节点上完成事务的工具,它经常被用在业务逻辑层将多个数据库操作组织成业务事务的场景,可以做到透明的可分布式事务控制和隐式失败回滚。但与此同时也经常有人提到TransactionScope有性能和部署方面的问题,关于这一点,根据MSDN的&&的说法,当一个TransactionScope包含的操作是同一个数据库连接时,它的行为与SqlTransaction是类似的。当它在多个数据库连接上进行数据操作时,则会将本地数据库事务提升为分布式事务,而这种提升要求各个节点均安装并启动DTC服务来支持分布式事务的协调工作,它的性能与本地数据库事务相比会低很多,这也是CAP定律说的分布式系统的Consistency和Availability不可兼得的典型例子。所以当我们选择是否使用TransactionScope时,一定要确认它会不会导致不想发生的分布式事务,也应该确保事务尽快做完它该做的事情,为了确认事务是否被提升我们可以用SQL Profiler去跟踪相关的事件。
然后再来看一看Entity Framework,其实EF也跟事务有关系。它的Context概念来源于Unit of Work模式,Context记录提交前的所有Entity变化,并在SaveChanges方法调用时发起真正的数据库操作,SaveChanges方法在默认情况下隐含一个事务,并且试图使用乐观并发控制来提交数据,但是为了进行并发控制我们需要将Entity Property的ConcurrencyMode设置为Fixed才行,否则EF不理会在此Entity上面发生的并发修改,这一点可以参考MSDN&。微软推荐大家使用以下方法来捕获冲突的并发操作,并使用RefreshMode来选择覆盖或丢弃失败的操作:
// Try to save changes, which may cause a conflict.
int num = context.SaveChanges();
Console.WriteLine("No conflicts. " +
num.ToString() + " updates saved.");
catch (OptimisticConcurrencyException)
// Resolve the concurrency conflict by refreshing the
// object context before re-saving changes.
context.Refresh(RefreshMode.ClientWins, orders);
// Save changes.
context.SaveChanges();
Console.WriteLine("OptimisticConcurrencyException "
+ "handled and changes saved");
当然除了乐观并发控制我们还可以对冲突特别频繁、冲突解决代价很大的用例进行悲观并发控制。悲观并发基本思想是不让数据被同时离线修改,也就是像源码管理里面&加锁&功能一样,码农甲锁上了这个文件,乙就不能再修改了,这样一来这个文件就不可能发生冲突,悲观并发控制实现的方式比如数据行加IsLocked字段等。
最后为了进行多Context事务,当然还可以混合使用TransactionScope和EF。
好了理论简单介绍完,下面的例子是几种不同的方法对并发控制的效果,需求是每个Member都有个HasMessage字段,初始为False,我们需要给其中一个Member加入唯一一条MemberMessage,并将Member.HasMessage置为True。
建库脚本:
&View Code
CREATE DATABASE [TransactionTest]GO
USE [TransactionTest]GO
CREATE TABLE [dbo].[Member](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](32) NOT NULL,
[HasMessage] [bit] NOT NULL, CONSTRAINT [PK_Member] PRIMARY KEY CLUSTERED (
[Id] ASC)WITH (PAD_INDEX
= OFF, STATISTICS_NORECOMPUTE
= OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS
= ON, ALLOW_PAGE_LOCKS
= ON) ON [PRIMARY]) ON [PRIMARY]GOSET IDENTITY_INSERT [dbo].[Member] ONINSERT [dbo].[Member] ([Id], [Name], [HasMessage]) VALUES (1, N'Tom', 0)INSERT [dbo].[Member] ([Id], [Name], [HasMessage]) VALUES (2, N'Jerry', 0)SET IDENTITY_INSERT [dbo].[Member] OFF
CREATE TABLE [dbo].[MemberMessage](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Message] [nvarchar](128) NOT NULL,
[MemberId] [int] NOT NULL, CONSTRAINT [PK_MemberMessage] PRIMARY KEY CLUSTERED (
[Id] ASC)WITH (PAD_INDEX
= OFF, STATISTICS_NORECOMPUTE
= OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS
= ON, ALLOW_PAGE_LOCKS
= ON) ON [PRIMARY]) ON [PRIMARY]GO
ALTER TABLE [dbo].[MemberMessage]
WITH CHECK ADD
CONSTRAINT [FK_MemberMessage_Member] FOREIGN KEY([MemberId])REFERENCES [dbo].[Member] ([Id])GOALTER TABLE [dbo].[MemberMessage] CHECK CONSTRAINT [FK_MemberMessage_Member]GO
方法1:不使用TransactionScope,只依赖Entity各字段的默认并发控制。
Context和Entity定义
&View Code
public class MyDbContext : DbContext{
public MyDbContext() : base("TransactionTest") { }
public MyDbContext(string connectionString) :
base(connectionString)
public DbSet&Member& Members { }}
[Table("Member")]public class Member{
public int Id { }
public string Name { }
public bool HasMessage { }
public virtual ICollection&MemberMessage& Messages { }}
[Table("MemberMessage")]public class MemberMessage{
public int Id { }
public string Message { }
public int MemberId { }
[ForeignKey("M
using (var context = new MyDbContext())
var tom = context.Members.FirstOrDefault(m =& m.Id == 1);
if (tom != null && !tom.HasMessage)
Console.WriteLine("Press Enter to Insert MemberMessage...");
Console.ReadLine();
tom.Messages.Add(new MemberMessage()
Message = "Hi Tom!"
tom.HasMessage =
context.SaveChanges();
Console.WriteLine("Insert Completed!");
}}catch (Exception ex){
Console.WriteLine("Insert Failed: " + ex);}
同时运行两个程序,结果是无法确保不重复插入
通过分析不难发现,该场景的并发控制关键就在于插入前检查HasMessage如果是False,则插入MemberMessage后更新Member.HasMessage字段时需要再次检查数据库中HasMessage字段是否为False,如果为True就是有其他人并发的更改了该字段,本次保存应该回滚或做其他处理。所以为此需要有针对性的加入并发控制。
方法2:给HasMessage字段加上并发检查
[Table("Member")]
public class Member
public int Id { get; set; }
public string Name { get; set; }
[ConcurrencyCheck]
public bool HasMessage { get; set; }
public virtual ICollection&MemberMessage& Messages { get; set; }
仍然使用方法1的测试代码,结果则是其中一次数据插入会抛出OptimisticConcurrencyException,也就是说防止重复插入数据的目的已经达到了。
那回过头来看看是否可以使用TransactionScope对EF进行并发控制,于是有方法3:使用TransactionScope但不给Entity加入并发检查
Context和Entity的定义与方法1完全一致,测试代码为
&View Code
using (var scope = new System.Transactions.TransactionScope())
using (var context = new MyDbContext())
var tom = context.Members.FirstOrDefault(m =& m.Id == 1);
if (tom != null && !tom.HasMessage)
Console.WriteLine("Press Enter to Insert MemberMessage...");
Console.ReadLine();
tom.Messages.Add(new MemberMessage()
Message = "Hi Tom!"
tom.HasMessage =
context.SaveChanges();
Console.WriteLine("Insert Completed!");
}}catch (Exception ex){
Console.WriteLine("Insert Failed: " + ex);}
同样启动两个程序测试,发现其中一次保存操作抛出DbUpdateException,其内部原因是Transaction死锁导致该操作被作为牺牲者。所以看起来也可以达到并发控制的效果,这种方式的优点是不需要去仔细辨别业务中哪些操作会导致字段的并发更新冲突,所有的Entity都可以不加ConcurrencyCheck,缺点则是当冲突不多的时候这种死锁竞争协调与乐观并发控制相比性能会低些。
最后为了完备测试各种组合,我们试一试方法4:既使用TransactionScope,又在HasMessage字段上加入ConcurrencyCheck,Entity代码参考方法1,测试代码则参考方法3,结果仍然是TransactionScope检测到死锁并选择其中一个竞争者抛出异常。
TransactionScope用或不用主要取决于是否需要进行分布式事务
即使不需要分布式事务,TransactionScope也可以用于没有精力仔细分析哪些Entity的字段需要进行并发检查的时候
如果能够细粒度分析并发场景,则推荐使用EF自带的并发控制机制
阅读(...) 评论()
随笔 - 15505
评论 - 1173&&&&&&&&& 之前写过一篇关于《》的文章,但今天又测试了一下,发现前一篇文章有很多问题,这里再把问题说一下。
一 什么时间会把你的transactionscope提升为分布式事务,即要使用MSDTC服务
  当你的WEB服务器与数据库服务器在同台电脑上,对同一个库进行操作时,它不会提升为分布式事务
  当你的WEB服务器与数据库服务器在同台电脑上,,对于同一个库,建立多个数据上下文时,它不会提升为分布式事务
  当你的WEB服务器与数据库服务器在同台电脑上,,当你操作两个库的表,这时才会提升为分布式事
&&&&& 当你的WEB服务器与数据库服务器不在同台电脑上,每次都会引发MSDTC
二 案例分析:
public class DbBase : Commons.Data.DbContextRepositoryBase
public DbBase()
: base(Commons.Data.DbFactory.Intance(System.Configuration.ConfigurationManager.ConnectionStrings["testEntities1"].ToString(), 2, 0))
public class DbBase2 : Commons.Data.DbContextRepositoryBase
public DbBase2()
: base(Commons.Data.DbFactory.Intance(System.Configuration.ConfigurationManager.ConnectionStrings["testEntities2"].ToString(), 2, 1))
public class ReviewRepository : DbBase
public class TestRepository : DbBase
public void Insert()
var product = new Product
Info = "test",
Name = "test",
var product_Comment = new Product_Comment
CommentInfo = "test",
CommentTitle = "Test",
ProductID = 1,
UserID = 1
var review = new Review
CreateDate = DateTime.Now,
Info = "test",
ObjID = 1,
ObjType = 1,
Status = 100,
UserID = 1,
using (var trans = new TransactionScope())
//var testEntities = new testEntities();
// var testEntities2 = new testEntities();
一个dbcontext对象不发生MSDTC
//testEntities.Product.AddObject(product);
//testEntities.Review.AddObject(review);
//testEntities.SaveChanges();
#endregion
多个dbcontext对象也不发生MSDTC
//testEntities.Product.Add(product);
//testEntities.SaveChanges();
//testEntities2.Review.Add(review);
//testEntities2.SaveChanges();
#endregion
#region 自己生产的DbContext对象也没有发生MSDTC
base.Insert&Product&(product);
base.Insert&Product_Comment&(product_Comment);
new ReviewRepository().Insert&Review&(review);
#endregion
测试环境:SQLSERVER2008在一台服务器
     IIS7在别一台服务器
感谢阅读!
阅读(...) 评论()[ASP.net教程]转载TransactionScope使用说明
你的位置:
[ASP.net教程]转载TransactionScope使用说明
如果在C#中使用TransactionScope类(分布式事务),则须注意如下事项:1、在项目中引用using System.Transactions命名空间(先要在添加net组件的引用);3、对MSDTC组件设置:&步骤:& 在控制面板---&管理工具---&服务 中,开启Distributed Transaction Coordinator 服务。&a.控制面板-&管理工具-&组件服务-&计算机-&我的电脑-&右键-&属性&b.选择MSDTC页, 确认"使用本地协调器"&c.点击下方"安全配置"按钮&d.勾选: "允许网络DTC访问","允许远程客户端","允许入站","允许出站","不要求进行身份验证".&e.对于数据库服务器端, 可选择"要求对呼叫方验证"&f.勾选:"启用事务Internet协议(TIP)事务"。&g.在双方防火墙中增加MSDTC.exe例外&& 可用命令行: netsh firewall set allowedprogram %windir%\system32\msdtc.exe MSDTC enable4、重启IIS服务器。注意:我们只要确保数据库的打开操作是在事务范围内打开就行了。这样就可以做到事务的正确操作。如果WEB服务器和数据库是在同一台服务器上,TransactionScope使用的是本地事务,这时不需要配置MSDTC。 如果WEB服务器和数据库不在同一台服务器上,TransactionScope会自动提升事务级别为分布式事务,这时就需要配置MSDTC。配置很简单的,网上有教程,做两次就知道了。2、具体示例如下:TransactionScope是.Net Framework 2.0滞后,新增了一个名称空间。它的用途是为数据库访问提供了一个&轻量级&[区别于:SqlTransaction]的事物。使用之前必须添加对 System.Transactions.dll 的引用。&&&&&& 下列代码就是一个正在创建的事务,这个事务自身还封装了多个数据库查询。只要任意一个 SqlCommand 对象引发异常,程序流控制就会跳出 TransactionScope 的 using 语句块,随后,TransactionScope 将自行释放并回滚该事务。由于这段代码使用了 using 语句,所以 SqlConnection 对象和 TransactionScope 对象都将被自动调用Dispose()释放。由此可见,只需添加很少的几行代码,您就可以构建出一个事务模型,这个模型可以对异常进行处理,执行结束后会 自行清理,此外,它还可以对命令的提交或回滚进行管理。//创建TransactionScopeusing (TransactionScope tsCope= new TransactionScope()){ using (SqlConnection cn2005= new SqlConnection(someSql2005)) { SqlCommand cmd= new SqlCommand(sqlUpdate, cn2005); cn2005.Open(); cmd.ExecuteNonQuery(); } using (SqlConnection cn2005= new SqlConnection(anotherSql2005)) { SqlCommand cmd= new SqlCommand(sqlDelete, cn2005); cn2005.Open(); cmd.ExecuteNonQuery(); } plete();}& 连接字符串关键字(Enlist)&&&&&& SqlConnection.ConnectionString 属性支持关键字 Enlist,该关键字指示 System.Data.SqlClient 是否将检测事务上下文并自动在分布式事务中登记连接。 如果 Enlist=true,连接将自动在打开的线程的当前事务上下文中登记。 如果 Enlist=false,SqlClient 连接不会与分布式事务进行交互。 Enlist 的默认值为 true。 如果连接字符串中未指定 Enlist,若在连接打开时检测到一个,连接将自动在分布式事务中登记。&&Server=(local)SQL2005;Database=NIntegrated Security=SSPI;auto-enlist=false&&&&&&& 上面所看到的示例中我们使用了TransactionScope的默认设置。TransactionScope有三种模式:TransactionScopeOptions描述Required如果已经存在一个事务,那么这个事务范围将加入已有的事务。否则,它将创建自己的事务。RequiresNew这个事务范围将创建自己的事务。Suppress如果处于当前活动事务范围内,那么这个事务范围既不会加入氛围事务 (ambient transaction),也不会创建自己的事务。当部分代码需要留在事务外部时,可以使用该选项。&&&&&& 您可以在代码的任何位置上随是查看是否存在事务范围,具体方法就是查看 System.Transactions.Transaction.Current 属性。如果这个属性为&null&,说明不存在当前事务。&&&&&& 若要更改 TransactionScope 类的默认设置,您可以创建一个 TransactionOptions 对象,然后通过它在 TransactionScope 对象上设置隔离级别和事务的超时时间。TransactionOptions 类有一个 IsolationLevel 属性,通过这个属性可以更改隔离级别,例如从默认的可序列化 (Serializable) 改为ReadCommitted,甚至可以改为 SQL Server 2005 引入的新的快照 (Snapshot) 级别。(请记住,隔离级别仅仅是一个建议。大多数数据库引擎会试着使用建议的隔离级别,但也可能选择其他级别。)此 外,TransactionOptions 类还有一个 TimeOut 属性,这个属性可以用来更改超时时间(默认设置为 1 分钟)。&&&&&& 下列代码中使用了默认的 TransactionScope 对象及其默认构造函数。也就是说,它的隔离级别设置为可序列化 (Serializable),事务的超时时间为 1 分钟,而且 TransactionScopeOptions 的设置为 Required。TransactionOptions tOpt= new TransactionOptions();//设置TransactionOptions模式tOpt.IsolationLevel= IsolationLevel.ReadC// 设置超时间隔为2分钟,默认为60秒tOpt.Timeout= new TimeSpan(0,2,0);string cnString= ConfigurationManager.ConnectionStrings["sql2005DBServer"].ConnectionString);using (TransactionScope tsCope= new TransactionScope(TransactionScopeOption.RequiresNew, tOpt)){using (SqlConnection cn2005= new SqlConnection(cnString){SqlCommand cmd= new SqlCommand(updateSql1, cn2005);cn2005.Open();cmd.ExecuteNonQuery();}plete();}&&&&&&& 嵌套应用&&&&& 如下列代码,假设 Method1 创建一个 TransactionScope,针对一个数据库执行一条命令,然后调用 Method2。Method2 创建一个自身的 TransactionScope,并针对一个数据库执行另一条命令。&&&&&&private void Method1(){using (TransactionScope ts=new TransactionScope(TransactionScopeOption.Required)){using (SqlConnection cn2005= new SqlConnection()){SqlCommand cmd= new SqlCommand(updateSql1, cn2005);cn2005.Open();cmd.ExecuteNonQuery();}Method2();ts.Complete();}}private void Method2(){using (TransactionScope ts=new TransactionScope(TransactionScopeOption.RequiresNew)){using (SqlConnection cn2005= new SqlConnection()){SqlCommand cmd= new SqlCommand(updateSql2, cn2005);cn2005.Open();cmd.ExecuteNonQuery();}ts.Complete();}}&&&&&& 总结:&&&&&& 进入和退出事务都要快,这一点非常重要,因为事务会锁定宝贵的资源。最佳实践要求我们在需要使用事务之前再去创建它,在需要对其执行命令前迅速打开连接, 执行动作查询 (Action Query),并尽可能快地完成和释放事务。在事务执行期间,您还应该避免执行任何不必要的、与数据库无关的代码,这能够防止资源被毫无疑义地锁定过长的 时间。/blsong/archive//1798987.html
、 、 、 、 、

我要回帖

更多关于 spring scope 默认 的文章

 

随机推荐