第五节:EF Core中的三类事务(SaveChanges、DbContextTransaction、TransactionScope)
一. 说明
EF版本的事务介绍详见:
第七节: EF的三种事务的应用场景和各自注意的问题(SaveChanges、DBContextTransaction、TransactionScope)。
本节主要介绍EF Core下的三种事务的用法和各自的使用场景,其中SaveChanges和DBContextTransaction事务与EF版本的基本一致,在该章节中补充一些新的使用场景和配置方式,TransactionScope环境事务与EF 版本的有着本质的区别,它目前不支持分布式数据库事务。
后面章节将继续介绍事务的基础概念、事务的隔离级别和带来的各种问题。
二. 默认事务(SaveChanges)
(1).默认情况下,如果数据库提供程序支持事务,单个 SaveChanges() 调用中的所有变更都会在一个事务中被提交。如果其中任何一个变更失败了, 那么事务就会回滚,没有任何变更会被应用到数据库。这意味着 SaveChanges() 能够确保要么成功保存,要么在发生错误时不对数据库做任何修改。
(2).关闭默认事务:context.Database.AutoTransactionsEnabled = false; 如:Test3()方法,第一条数据保存成功,第二条失败。
代码分享:
1 /// <summary>
2 /// 全部成功
3 /// </summary>
4 public static void Test1()
5 {
6 using (EFDB01Context db = new EFDB01Context())
7 {
8 db.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
9 db.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员2", addTime = DateTime.Now });
10 db.SaveChanges();
11 }
12 }
13
14 /// <summary>
15 /// 全部失败
16 /// </summary>
17 public static void Test2()
18 {
19 using (EFDB01Context db = new EFDB01Context())
20 {
21 try
22 {
23 db.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
24 db.T_RoleInfor.Add(new T_RoleInfor() { id = 123, roleName = "管理员2", addTime = DateTime.Now });
25 db.SaveChanges();
26 }
27 catch (Exception)
28 {
29 Console.WriteLine("出错了,两条数据都没有执行成功");
30 }
31 }
32 }
33
34 /// <summary>
35 /// 第一条成功,第二条失败
36 /// </summary>
37 public static void Test3()
38 {
39 using (EFDB01Context db = new EFDB01Context())
40 {
41 try
42 {
43 //关闭SaveChanges的默认事务
44 db.Database.AutoTransactionsEnabled = false;
45
46 db.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
47 db.T_RoleInfor.Add(new T_RoleInfor() { id = 123, roleName = "管理员2", addTime = DateTime.Now });
48
49 //db.T_UserInfor.Add(new T_UserInfor() { id = Guid.NewGuid().ToString("N"), userName = "管理员1", addTime = DateTime.Now });
50 //db.T_UserInfor.Add(new T_UserInfor() { id = Guid.NewGuid().ToString("N")+"123", userName = "管理员2", addTime = DateTime.Now });
51
52 db.SaveChanges();
53 }
54 catch (Exception)
55 {
56 Console.WriteLine("出错了,第一条数据插入成功了");
57 }
58 }
59 }
三. DbContextTransaction
1. 使用方式
BeginTransaction开启事务、Commit提交事务、Rollback回滚事务、Dispose销毁,如果用Using包裹的话,不再需要手动Rollback,走完Using会自动回滚。如果不用Using包裹事务,就需要在Catch中手动RollBack回滚,并且最好最后手动的Dispose一下。(如SameDbContext文件夹中的Test1和Test2方法)
2. 使用场景
A. 同一个上下文多个SaveChanges的方法(如:自增主键后续要用到,如Test2方法)、SaveChanges和EF调用SQL语句混用(如Test2方法)
1 /// <summary>
2 /// 三条添加语句共享同一个事务,最后使用 transaction.Commit() 统一提交,三条全部执行成功,则影响到数据库,
3 /// 如果任何一个命令失败,则在事务被回收(Dispose)时会自动回滚,对数据库无影响。
4 /// </summary>
5 public static void Test1()
6 {
7 using (EFDB01Context db = new EFDB01Context())
8 {
9 using (var transaction = db.Database.BeginTransaction())
10 {
11 try
12 {
13 db.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
14 db.SaveChanges();
15
16 db.T_RoleInfor.Add(new T_RoleInfor() { id = 111, roleName = "管理员2", addTime = DateTime.Now }); //报错
17 db.SaveChanges();
18
19 string sql1 = @"insert into T_RoleInfor (roleName,roleDescription,addTime) values (@roleName,@roleDescription,@addTime)";
20 SqlParameter[] pars1 ={
21 new SqlParameter("@roleName","管理员3"),
22 new SqlParameter("@roleDescription","txt11"),
23 new SqlParameter("@addTime",DateTime.Now)
24 };
25 db.Database.ExecuteSqlCommand(sql1, pars1);
26 transaction.Commit();
27
28 Console.WriteLine("成功了");
29 }
30 catch (Exception)
31 {
32 Console.WriteLine("失败了");
33 }
34 }
35 }
36 }
37
38 /// <summary>
39 /// 如果不用Using包裹事务,就需要在Catch中手动RollBack回滚
40 /// </summary>
41 public static void Test2()
42 {
43 using (EFDB01Context db = new EFDB01Context())
44 {
45 var transaction = db.Database.BeginTransaction();
46 try
47 {
48 var d1 = new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now };
49 db.T_RoleInfor.Add(d1);
50 db.SaveChanges();
51
52 db.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员2"+d1.id, addTime = DateTime.Now });
53 db.SaveChanges();
54
55 string sql1 = @"insert into T_RoleInfor (roleName,roleDescription,addTime) values (@roleName,@roleDescription,@addTime)";
56 SqlParameter[] pars1 ={
57 new SqlParameter("@roleName","管理员3"),
58 new SqlParameter("@roleDescription","txt11"),
59 new SqlParameter("@addTime",DateTime.Now)
60 };
61 db.Database.ExecuteSqlCommand(sql1, pars1);
62 transaction.Commit();
63
64 Console.WriteLine("成功了");
65
66 }
67 catch (Exception)
68 {
69 transaction.Rollback();
70 Console.WriteLine("失败了");
71 }
72 finally
73 {
74 transaction.Dispose();
75 }
76
77 }
78 }
B. 同一个数据库多个上下文但“同一个连接”的事务。其中一个上下文开启事务,另外上下文通过UseTransaction方法来实现共享事务。
情况①:
EFDB01Context直接在OnConfiguring中写死连接字符串,多次new上下文,如Test1方法,则是多个连接,不能共享事务。

1 /// <summary>
2 /// 情况一:在OnConfiguring中书写连接字符串,创建两个上下文,相当于两个连接,两个连接之间不能通过使用UseTransaction,建立事务连接。
3 /// 会报下面的错。
4 /// The specified transaction is not associated with the current connection. Only transactions associated with the current connection may be used.
5 /// </summary>
6 public static void Test1()
7 {
8 using (EFDB01Context context1 = new EFDB01Context())
9 {
10 using (var transaction = context1.Database.BeginTransaction())
11 {
12 try
13 {
14 context1.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
15 context1.SaveChanges();
16
17 using (EFDB01Context context2 = new EFDB01Context())
18 {
19 context2.Database.UseTransaction(transaction.GetDbTransaction());
20
21 context1.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
22 context1.SaveChanges();
23 }
24
25 //统一提交
26 transaction.Commit();
27 Console.WriteLine("成功了");
28 }
29 catch (Exception ex)
30 {
31 Console.WriteLine(ex.Message);
32 }
33 }
34 }
35
36
37 }
情况②:
EFDB01Context2通过 public EFDB01Context2(DbContextOptions<EFDB01Context2> options) : base(options)这种形式的构造函数,然后new的时候 统一传入: new DbContextOptionsBuilder<EFDB01Context2>().UseSqlServer(new SqlConnection(connectionString)).Options;,从而共享连接,如Test2方法。

1 /// <summary>
2 /// 情况二:通过父类构造函数
3 /// </summary>
4 public static void Test2()
5 {
6 var connectionString = "Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
7 //将连接拿出来,传到多个上下文中,这样是共享同一个连接
8 var option = new DbContextOptionsBuilder<EFDB01Context2>().UseSqlServer(new SqlConnection(connectionString)).Options;
9
10 using (var context1 = new EFDB01Context2(option))
11 {
12 using (var transaction = context1.Database.BeginTransaction())
13 {
14 try
15 {
16 context1.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
17 context1.SaveChanges();
18
19 using (var context2 = new EFDB01Context2(option))
20 {
21 context2.Database.UseTransaction(transaction.GetDbTransaction());
22
23 context1.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
24 context1.SaveChanges();
25 }
26
27 //统一提交
28 transaction.Commit();
29 Console.WriteLine("成功了");
30 }
31 catch (Exception ex)
32 {
33 Console.WriteLine(ex.Message);
34 }
35 }
36 }
37 }
情况③:
EFDB01Context3通过 传入SqlConnection来实现共享连接,如Test3方法。

1 public static void Test3()
2 {
3 var connectionString = "Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
4 //将连接拿出来,传到多个上下文中,这样是共享同一个连接
5 var connection = new SqlConnection(connectionString);
6
7 using (var context1 = new EFDB01Context3(connection))
8 {
9 using (var transaction = context1.Database.BeginTransaction())
10 {
11 try
12 {
13 context1.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
14 context1.SaveChanges();
15
16 using (var context2 = new EFDB01Context3(connection))
17 {
18 context2.Database.UseTransaction(transaction.GetDbTransaction());
19
20 context1.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
21 context1.SaveChanges();
22 }
23
24 //统一提交
25 transaction.Commit();
26 Console.WriteLine("成功了");
27 }
28 catch (Exception ex)
29 {
30 Console.WriteLine(ex.Message);
31 }
32 }
33 }
34 }
C. 多种数据库技术同一个数据库的事务
如ADO.Net和EF共同使用,利用方法 “UseTransaction”共享同一个事务,共同提交。 如:Test1方法
1 /// <summary>
2 /// ADO.Net 和 EF混用,多种数据库技术访问同一个数据库
3 /// </summary>
4 public static void Test1()
5 {
6 var conStr = @"Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
7 using (var connection=new SqlConnection(conStr))
8 {
9 connection.Open();
10 using (var transaction=connection.BeginTransaction())
11 {
12 try
13 {
14 //ADO.Net
15 var command = connection.CreateCommand();
16 command.Transaction = transaction;
17 command.CommandText = "DELETE FROM T_RoleInfor";
18 command.ExecuteNonQuery();
19
20 //EF
21 var options = new DbContextOptionsBuilder<EFDB01Context>().UseSqlServer(connection).Options;
22 using (var context = new EFDB01Context(options))
23 {
24 context.Database.UseTransaction(transaction);
25 context.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
26 context.SaveChanges();
27 }
28 //综合提交
29 transaction.Commit();
30
31 Console.WriteLine("成功了");
32
33 }
34 catch (Exception ex)
35 {
36 Console.WriteLine(ex.Message);
37 }
38 }
39
40 }
41 }
四. 环境事务
1.使用方式
new TransactionScope创建事务、Complete提交事务、 Transaction.Current.Rollback();回滚事务、Dispose销毁对象。如果用Using包裹的话,不再需要手动Rollback,走完Using会自动回滚。如果不用Using包裹事务,就需要在Catch中手动RollBack回滚,并且最好最后手动的Dispose一下。
2.用途
A. 同一个上下文的事务。(多个SaveChanges(自增主键后续用到的情况)、SaveChanges和EF调用SQL语句混用)(如Test1方法)
1 /// <summary>
2 /// A. 同一个上下文的事务。(多个SaveChanges(自增主键后续用到的情况)、SaveChanges和EF调用SQL语句混用)
3 /// </summary>
4 public static void Test1()
5 {
6 using (EFDB01Context1 db = new EFDB01Context1())
7 {
8 using (var scope = new TransactionScope(/*TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }*/))
9 {
10 try
11 {
12 var data1 = new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now };
13 db.T_RoleInfor.Add(data1);
14 db.SaveChanges();
15
16 db.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员2" + data1.id, addTime = DateTime.Now }); //报错
17 db.SaveChanges();
18
19 string sql1 = @"insert into T_RoleInfor (roleName,roleDescription,addTime) values (@roleName,@roleDescription,@addTime)";
20 SqlParameter[] pars1 ={
21 new SqlParameter("@roleName","管理员3"),
22 new SqlParameter("@roleDescription","txt11"),
23 new SqlParameter("@addTime",DateTime.Now)
24 };
25 db.Database.ExecuteSqlCommand(sql1, pars1);
26 scope.Complete();
27
28
29 Console.WriteLine("成功了");
30 }
31 catch (Exception)
32 {
33 Console.WriteLine("失败了");
34 }
35 }
36 }
37 }
1 /// <summary>
2 /// A. 同一个上下文的事务。(多个SaveChanges(自增主键后续用到的情况)、SaveChanges和EF调用SQL语句混用)
3 /// </summary>
4 public static void Test1()
5 {
6 using (EFDB01Context1 db = new EFDB01Context1())
7 {
8 using (var scope = new TransactionScope(/*TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }*/))
9 {
10 try
11 {
12 var data1 = new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now };
13 db.T_RoleInfor.Add(data1);
14 db.SaveChanges();
15
16 db.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员2" + data1.id, addTime = DateTime.Now }); //报错
17 db.SaveChanges();
18
19 string sql1 = @"insert into T_RoleInfor (roleName,roleDescription,addTime) values (@roleName,@roleDescription,@addTime)";
20 SqlParameter[] pars1 ={
21 new SqlParameter("@roleName","管理员3"),
22 new SqlParameter("@roleDescription","txt11"),
23 new SqlParameter("@addTime",DateTime.Now)
24 };
25 db.Database.ExecuteSqlCommand(sql1, pars1);
26 scope.Complete();
27
28
29 Console.WriteLine("成功了");
30 }
31 catch (Exception)
32 {
33 Console.WriteLine("失败了");
34 }
35 }
36 }
37 }
B. 多种数据库技术访问同一个数据库的事务 (如Test2方法)
1 /// <summary>
2 /// B. 多种数据库技术访问同一个数据库的事务
3 /// </summary>
4 public static void Test2()
5 {
6 var conStr = @"Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
7 using (var connection = new SqlConnection(conStr))
8 {
9 connection.Open();
10 using (var scope = new TransactionScope())
11 {
12 try
13 {
14 //ADO.Net
15 var command = connection.CreateCommand();
16 command.CommandText = "DELETE FROM T_RoleInfor";
17 command.ExecuteNonQuery();
18
19 //EF
20 using (var context = new EFDB01Context1())
21 {
22 context.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
23 context.SaveChanges();
24 }
25 //综合提交
26 scope.Complete();
27
28 Console.WriteLine("成功了");
29
30 }
31 catch (Exception ex)
32 {
33 Console.WriteLine(ex.Message);
34 }
35 }
36 }
37 }
1 /// <summary>
2 /// B. 多种数据库技术访问同一个数据库的事务
3 /// </summary>
4 public static void Test2()
5 {
6 var conStr = @"Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
7 using (var connection = new SqlConnection(conStr))
8 {
9 connection.Open();
10 using (var scope = new TransactionScope())
11 {
12 try
13 {
14 //ADO.Net
15 var command = connection.CreateCommand();
16 command.CommandText = "DELETE FROM T_RoleInfor";
17 command.ExecuteNonQuery();
18
19 //EF
20 using (var context = new EFDB01Context1())
21 {
22 context.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
23 context.SaveChanges();
24 }
25 //综合提交
26 scope.Complete();
27
28 Console.WriteLine("成功了");
29
30 }
31 catch (Exception ex)
32 {
33 Console.WriteLine(ex.Message);
34 }
35 }
36 }
37 }
C. 同一个数据库多个不同的上下文是支持的(如Test3方法)
上下文代码:
1 public partial class EFDB01Context1 : DbContext
2 {
3 public virtual DbSet<T_RoleInfor> T_RoleInfor { get; set; }
4 public virtual DbSet<T_UserInfor> T_UserInfor { get; set; }
5
6 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
7 {
8 optionsBuilder.UseSqlServer("Server=localhost;Database=EFDB01;User ID=sa;Password=123456;");
9 }
10
11 protected override void OnModelCreating(ModelBuilder modelBuilder)
12 {
13 modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
14
15 modelBuilder.Entity<T_RoleInfor>(entity =>
16 {
17 entity.Property(e => e.roleDescription).IsUnicode(false);
18
19 entity.Property(e => e.roleName).IsUnicode(false);
20 });
21
22 modelBuilder.Entity<T_UserInfor>(entity =>
23 {
24 entity.Property(e => e.id)
25 .IsUnicode(false)
26 .ValueGeneratedNever();
27
28 entity.Property(e => e.userName).IsUnicode(false);
29
30 entity.Property(e => e.userSex).IsUnicode(false);
31 });
32 }
33 }
1 public partial class EFDB01Context1 : DbContext
2 {
3 public virtual DbSet<T_RoleInfor> T_RoleInfor { get; set; }
4 public virtual DbSet<T_UserInfor> T_UserInfor { get; set; }
5
6 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
7 {
8 optionsBuilder.UseSqlServer("Server=localhost;Database=EFDB01;User ID=sa;Password=123456;");
9 }
10
11 protected override void OnModelCreating(ModelBuilder modelBuilder)
12 {
13 modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
14
15 modelBuilder.Entity<T_RoleInfor>(entity =>
16 {
17 entity.Property(e => e.roleDescription).IsUnicode(false);
18
19 entity.Property(e => e.roleName).IsUnicode(false);
20 });
21
22 modelBuilder.Entity<T_UserInfor>(entity =>
23 {
24 entity.Property(e => e.id)
25 .IsUnicode(false)
26 .ValueGeneratedNever();
27
28 entity.Property(e => e.userName).IsUnicode(false);
29
30 entity.Property(e => e.userSex).IsUnicode(false);
31 });
32 }
33 }
1 public partial class EFDB01Context2 : DbContext
2 {
3 public virtual DbSet<T_RoleInfor> T_RoleInfor { get; set; }
4 public virtual DbSet<T_UserInfor> T_UserInfor { get; set; }
5
6 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
7 {
8 optionsBuilder.UseSqlServer("Server=localhost;Database=EFDB01;User ID=sa;Password=123456;");
9 }
10
11 protected override void OnModelCreating(ModelBuilder modelBuilder)
12 {
13 modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
14
15 modelBuilder.Entity<T_RoleInfor>(entity =>
16 {
17 entity.Property(e => e.roleDescription).IsUnicode(false);
18
19 entity.Property(e => e.roleName).IsUnicode(false);
20 });
21
22 modelBuilder.Entity<T_UserInfor>(entity =>
23 {
24 entity.Property(e => e.id)
25 .IsUnicode(false)
26 .ValueGeneratedNever();
27
28 entity.Property(e => e.userName).IsUnicode(false);
29
30 entity.Property(e => e.userSex).IsUnicode(false);
31 });
32 }
33 }
1 public partial class EFDB01Context2 : DbContext
2 {
3 public virtual DbSet<T_RoleInfor> T_RoleInfor { get; set; }
4 public virtual DbSet<T_UserInfor> T_UserInfor { get; set; }
5
6 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
7 {
8 optionsBuilder.UseSqlServer("Server=localhost;Database=EFDB01;User ID=sa;Password=123456;");
9 }
10
11 protected override void OnModelCreating(ModelBuilder modelBuilder)
12 {
13 modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
14
15 modelBuilder.Entity<T_RoleInfor>(entity =>
16 {
17 entity.Property(e => e.roleDescription).IsUnicode(false);
18
19 entity.Property(e => e.roleName).IsUnicode(false);
20 });
21
22 modelBuilder.Entity<T_UserInfor>(entity =>
23 {
24 entity.Property(e => e.id)
25 .IsUnicode(false)
26 .ValueGeneratedNever();
27
28 entity.Property(e => e.userName).IsUnicode(false);
29
30 entity.Property(e => e.userSex).IsUnicode(false);
31 });
32 }
33 }
运行代码:
1 /// <summary>
2 ///C. 同一个数据库两个不同上下文是支持的
3 /// </summary>
4 public static void Test3()
5 {
6 using (var scope = new TransactionScope())
7 {
8 try
9 {
10 using (var context = new EFDB01Context1())
11 {
12 context.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
13 context.SaveChanges();
14 }
15 using (var context = new EFDB01Context2())
16 {
17 context.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
18 context.SaveChanges();
19 }
20
21 //综合提交
22 scope.Complete();
23
24 Console.WriteLine("成功了");
25 }
26 catch (Exception ex)
27 {
28 Console.WriteLine(ex.Message);
29 }
30 }
31 }
D. 不同数据库的上下文是不支持的,(如Test4方法,开启msdtc服务的步骤: cmd命令→ net start msdtc ,然后发现报错:This platform does not support distributed transactions.说明目前Core平台下不支持分布式事务)
上下文代码:
1 public partial class dbCore1Context : DbContext
2 {
3 public dbCore1Context()
4 {
5 }
6
7 public dbCore1Context(DbContextOptions<dbCore1Context> options)
8 : base(options)
9 {
10 }
11
12 public virtual DbSet<UserInfors> UserInfors { get; set; }
13
14 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
15 {
16 optionsBuilder.UseSqlServer("Server=localhost;Database=dbCore1;User ID=sa;Password=123456;");
17
18 }
19
20 protected override void OnModelCreating(ModelBuilder modelBuilder)
21 {
22 modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
23
24 modelBuilder.Entity<UserInfors>(entity =>
25 {
26 entity.Property(e => e.id).ValueGeneratedNever();
27 });
28 }
29 }
1 public partial class dbCore1Context : DbContext
2 {
3 public dbCore1Context()
4 {
5 }
6
7 public dbCore1Context(DbContextOptions<dbCore1Context> options)
8 : base(options)
9 {
10 }
11
12 public virtual DbSet<UserInfors> UserInfors { get; set; }
13
14 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
15 {
16 optionsBuilder.UseSqlServer("Server=localhost;Database=dbCore1;User ID=sa;Password=123456;");
17
18 }
19
20 protected override void OnModelCreating(ModelBuilder modelBuilder)
21 {
22 modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
23
24 modelBuilder.Entity<UserInfors>(entity =>
25 {
26 entity.Property(e => e.id).ValueGeneratedNever();
27 });
28 }
29 }
1 public partial class EFDB01Context1 : DbContext
2 {
3 public virtual DbSet<T_RoleInfor> T_RoleInfor { get; set; }
4 public virtual DbSet<T_UserInfor> T_UserInfor { get; set; }
5
6 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
7 {
8 optionsBuilder.UseSqlServer("Server=localhost;Database=EFDB01;User ID=sa;Password=123456;");
9 }
10
11 protected override void OnModelCreating(ModelBuilder modelBuilder)
12 {
13 modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
14
15 modelBuilder.Entity<T_RoleInfor>(entity =>
16 {
17 entity.Property(e => e.roleDescription).IsUnicode(false);
18
19 entity.Property(e => e.roleName).IsUnicode(false);
20 });
21
22 modelBuilder.Entity<T_UserInfor>(entity =>
23 {
24 entity.Property(e => e.id)
25 .IsUnicode(false)
26 .ValueGeneratedNever();
27
28 entity.Property(e => e.userName).IsUnicode(false);
29
30 entity.Property(e => e.userSex).IsUnicode(false);
31 });
32 }
33 }
1 public partial class EFDB01Context1 : DbContext
2 {
3 public virtual DbSet<T_RoleInfor> T_RoleInfor { get; set; }
4 public virtual DbSet<T_UserInfor> T_UserInfor { get; set; }
5
6 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
7 {
8 optionsBuilder.UseSqlServer("Server=localhost;Database=EFDB01;User ID=sa;Password=123456;");
9 }
10
11 protected override void OnModelCreating(ModelBuilder modelBuilder)
12 {
13 modelBuilder.HasAnnotation("ProductVersion", "2.2.0-rtm-35687");
14
15 modelBuilder.Entity<T_RoleInfor>(entity =>
16 {
17 entity.Property(e => e.roleDescription).IsUnicode(false);
18
19 entity.Property(e => e.roleName).IsUnicode(false);
20 });
21
22 modelBuilder.Entity<T_UserInfor>(entity =>
23 {
24 entity.Property(e => e.id)
25 .IsUnicode(false)
26 .ValueGeneratedNever();
27
28 entity.Property(e => e.userName).IsUnicode(false);
29
30 entity.Property(e => e.userSex).IsUnicode(false);
31 });
32 }
33 }
运行代码:
1 /// <summary>
2 ///D. 不同数据库之间的事务
3 /// </summary>
4 public static void Test4()
5 {
6 using (var scope = new TransactionScope())
7 {
8 try
9 {
10 using (var context = new EFDB01Context1())
11 {
12 context.T_RoleInfor.Add(new T_RoleInfor() { roleName = "管理员1", addTime = DateTime.Now });
13 context.SaveChanges();
14 }
15 using (var context = new dbCore1Context())
16 {
17 context.UserInfors.Add(new UserInfors() { id = Guid.NewGuid().ToString("N"), userName = "管理员1", userSex = "男" });
18 context.SaveChanges();
19 }
20
21 //综合提交
22 scope.Complete();
23
24 Console.WriteLine("成功了");
25 }
26 catch (Exception ex)
27 {
28 Console.WriteLine(ex.Message);
29 }
30 }
31 }
注:EF Core中的 System.Transactions 实现将不包括对分布式事务的支持,因此不能使用 TransactionScope 或 CommittableTransaction 来跨多个资源管理器协调事务。主要分布式事务需要依赖于 Windows 系统的 MSDTC 服务,但.NET Core要实现跨平台,基于跨平台的分布式事务没有统一的标准,后续版希望改进。
原文:https://www.cnblogs.com/yaopengfei/p/11387935.html


浙公网安备 33010602011771号