C# TransactionScope「建议收藏」

C# TransactionScope「建议收藏」TransactionScopeTransactionScope事务处理经常用到,老是用了又忘,做点记录。TransactionScope的定义跟使用介绍。TransactionScopeOptionTransactionScopeOption枚举型用来决定一个TransactionScope是用已有的事务,还是定义TransactionScope的新做一个事务,还是完全不用事务。默认是Required,Required表示如果已有事务,就加入该事务,否则新建一个事务。TransactionOp

大家好,又见面了,我是你们的朋友全栈君。

TransactionScope

TransactionScope事务处理经常用到,老是用了又忘,做点记录。
TransactionScope的定义使用介绍


TransactionScopeOption

TransactionScopeOption枚举型用来决定一个TransactionScope是用已有的事务,还是定义TransactionScope的新做一个事务,还是完全不用事务。默认是Required,Required表示如果已有事务,就加入该事务,否则新建一个事务。

TransactionOptions

TransactionOptions 结构体用来设置TransactionScope所用到事务的隔离级别超时时间
隔离级别参考这篇博文。(乐观锁


实践

做两张表

USE [Learning]
GO
CREATE TABLE [dbo].[Foo](
	[Id] [bigint] IDENTITY(1,1) NOT NULL,
	[Value] [nvarchar](50) NULL,
 CONSTRAINT [PK_Foo] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Bar](
	[Id] [bigint] IDENTITY(1,1) NOT NULL,
	[Value] [nvarchar](50) NULL,
 CONSTRAINT [PK_Bar] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

准备测试类
用了EntityFrameWorkCore的库,两个DbContext连同一个数据库。(本地测试的时候,连两个不同的数据库报错:EntityFrameWorkCore不支持分布式事务。。)

using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Transactions;
namespace LocalAppTest
{ 

public class FooDbContext : DbContext
{ 

public FooDbContext(DbContextOptions<FooDbContext> options) : base(options) { 
 }
public DbSet<Foo> Foo { 
 get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{ 

}
}
[Table("Foo")]
public class Foo
{ 

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { 
 get; set; }
[StringLength(50)]
public string Value { 
 get; set; }
}
public class BarDbContext : DbContext
{ 

public BarDbContext(DbContextOptions<BarDbContext> options) : base(options) { 
 }
public DbSet<Bar> Bar { 
 get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{ 

}
}
[Table("Bar")]
public class Bar
{ 

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { 
 get; set; }
[StringLength(50)]
public string Value { 
 get; set; }
}
public class TransactionScopeTest
{ 

public DbContextOptions<FooDbContext> FooOptions;
public DbContextOptions<BarDbContext> BarOptions;
public TransactionScopeTest()
{ 

FooOptions = (new DbContextOptionsBuilder<FooDbContext>()).UseSqlServer("server=localhost;database=Learning;integrated security=true;").Options;
BarOptions = (new DbContextOptionsBuilder<BarDbContext>()).UseSqlServer("server=localhost;database=Learning;integrated security=true;").Options;
}
public void Test()
{ 

using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { 
 IsolationLevel = IsolationLevel.ReadCommitted }))
{ 

using (var fooContext = new FooDbContext(FooOptions))
{ 

var foo = new Foo { 
 Value = "Hi" };
fooContext.Add(foo);
fooContext.SaveChanges();
using (var barContext = new BarDbContext(BarOptions))
{ 

var bar = new Bar { 
 Value = "Loser" };
barContext.Add(bar);
barContext.SaveChanges();
}
scope.Dispose();
}
}
}
}
}

调用测试代码

new TransactionScopeTest().Test();

以上,

  • 用了常用的 ReadCommitted 隔离级别。
  • 上述代码走到第一个 SaveChanges 方法的时候,Foo 表锁住,其他查询语句会等待;走到第二个 SaveChanges 方法的时候,Bar 表锁住,其他查询语句会等待。
  • Dispose 之后,表数据未更新,Foo 跟 Bar 两张表的其他查询语句正常执行。

再做个测试

using Microsoft.EntityFrameworkCore;
using System.Transactions;
using System.Linq;
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
namespace LocalAppTest
{ 

public class TransactionScopeTest
{ 

public DbContextOptions<FooDbContext> FooOptions;
public DbContextOptions<BarDbContext> BarOptions;
public TransactionScopeTest()
{ 

FooOptions = (new DbContextOptionsBuilder<FooDbContext>()).UseSqlServer("server=localhost;database=Learning;integrated security=true;").Options;
BarOptions = (new DbContextOptionsBuilder<BarDbContext>()).UseSqlServer("server=localhost;database=Learning;integrated security=true;").Options;
}       
public void Test2()
{ 

var tasks = new List<Task>();
int i = 0;
while (i < 100)
{ 

tasks.Add(Task.Run(() =>
{ 

using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions { 
 IsolationLevel = IsolationLevel.ReadCommitted }))
{ 

using (var fooContext = new FooDbContext(FooOptions))
{ 

var records = fooContext.Foo.ToList();
var foo = new Foo { 
 Value = Guid.NewGuid().ToString() };
fooContext.Add(foo);
fooContext.SaveChanges();
scope.Complete();
}
}
}));
i++;
}
Task.WaitAll(tasks.ToArray());
}
}
}

调用测试代码

new TransactionScopeTest().Test2();

Test2方法里面启用了100个线程,每个线程做两件事情:1.查询Foo表的数据;2.新增一条数据。执行下来,ReadCommitted 隔离级别下,没有发生死锁的现象。
把上述隔离级别改成 Serializable 后,再次执行,当某个线程占用资源的时候,其他线程会抛出异常,不再执行。

先记录到这。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/161946.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • c语言与java哪个更好_c语言和java哪个好?[通俗易懂]

    c语言与java哪个更好_c语言和java哪个好?[通俗易懂]看到这个问题,一定要参与一下,这两个语言我都太熟悉了,也用了很长时间。关于程序设计语言,有这么两句话:C语言,神一样的语言。java语言是一个神话。所以说这是两个神级语言,到底哪个好?下面咱们逐个分析一下:1。C语言,C语言是计算机程序设计语言史上具有划时代意义的语言,到今天为止也依然是主力语言。最新的2017年语言排行榜以微弱的差距排在第二位,远远高于榜单中其他语言的使用率,而且C语言的一众小弟…

  • NSGA2 算法Matlab实现「建议收藏」

    NSGA2 算法Matlab实现「建议收藏」为了能随时了解Matlab主要操作及思想。故本文贴上NSGA-Ⅱ算法Matlab实现(测试函数为ZDT1)。更多内容访问omegaxyz.comNSGA-Ⅱ就是在第一代非支配排序遗传算法的基础上改进而来,其改进主要是针对如上所述的三个方面:①提出了快速非支配排序算法,一方面降低了计算的复杂度,另一方面它将父代种群跟子代种群进行合并,使得下一代的种群从双倍的空间中进行选取,从而保留了

  • zipfile压缩文件夹_bad zip file

    zipfile压缩文件夹_bad zip fileimportzipfiledefzipDir(dirpath,outFULLName):zip=zipfile.ZipFile(outFULLName,’w’,zipfile.ZIP_DEFLATED)forpath,dirnames,filenamesinos.walk(dirpath):fpath=path.replace(dirpath,””)forfilenameinfilenames:zip.wri

  • Flume和Kafka的组合使用

    Flume和Kafka的组合使用在Windows系统中打开第1个cmd窗口,执行如下命令启动Zookeeper服务:cdC:\zookeeper\apache-zookeeper-3.7.1-bin.\bin\zkServer.cmd打开第2个cmd窗口,然后执行下面命令启动Kafka服务:cdC:\kafka_2.12-2.4.0\kafka_2.12-2.4.0.\bin\windows\kafka-server-start.bat.\config\server.properties打开第.

  • python+opencv图像模板匹配—多模板匹配

    python+opencv图像模板匹配—多模板匹配

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号