当前位置:网站首页>Three types of transactions in EF core (saveChanges, dbcontexttransaction, transactionscope)
Three types of transactions in EF core (saveChanges, dbcontexttransaction, transactionscope)
2022-06-23 23:51:00 【I left my life to work】
Default transaction (SaveChanges)
(1). By default , If the database provider supports transactions , Single SaveChanges() All changes in the invocation are committed in a transaction . If any of these changes fail , Then the transaction rolls back , No changes will be applied to the database . It means SaveChanges() Be able to ensure that it is either saved successfully , Or do not make any changes to the database when an error occurs .
(2). Close the default transaction :context.Database.AutoTransactionsEnabled = false; Such as :Test3() Method , First data saved successfully , The second failure .
/// <summary>
/// All success
/// </summary>
public static void Test1()
{
using (EFDB01Context db = new EFDB01Context())
{
db.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
db.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 2", addTime = DateTime.Now });
db.SaveChanges();
}
}
/// <summary>
/// All failed
/// </summary>
public static void Test2()
{
using (EFDB01Context db = new EFDB01Context())
{
try
{
db.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
db.T_RoleInfor.Add(new T_RoleInfor() {
id = 123, roleName = " Administrators 2", addTime = DateTime.Now });
db.SaveChanges();
}
catch (Exception)
{
Console.WriteLine(" Something went wrong , Neither data was successfully executed ");
}
}
}
/// <summary>
/// Article 1 success , The second failure
/// </summary>
public static void Test3()
{
using (EFDB01Context db = new EFDB01Context())
{
try
{
// close SaveChanges Default transaction for
db.Database.AutoTransactionsEnabled = false;
db.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
db.T_RoleInfor.Add(new T_RoleInfor() {
id = 123, roleName = " Administrators 2", addTime = DateTime.Now });
//db.T_UserInfor.Add(new T_UserInfor() { id = Guid.NewGuid().ToString("N"), userName = " Administrators 1", addTime = DateTime.Now });
//db.T_UserInfor.Add(new T_UserInfor() { id = Guid.NewGuid().ToString("N")+"123", userName = " Administrators 2", addTime = DateTime.Now });
db.SaveChanges();
}
catch (Exception)
{
Console.WriteLine(" Something went wrong , The first piece of data was inserted successfully ");
}
}
}
DbContextTransaction
1. Usage mode
BeginTransaction Open transaction 、Commit Commit transaction 、Rollback Roll back the transaction 、Dispose The destruction , If you use Using If the package , No more manual Rollback, Walk the Using Will automatically roll back . If not Using Parcel transaction , It needs to be in Catch Medium manual RollBack Roll back , And it's best to do it manually Dispose once .( Such as SameDbContext In folder Test1 and Test2 Method )
2. Use scenarios
A. Multiple in the same context SaveChanges Methods ( Such as : The auto increment primary key will be used later , Such as Test2 Method )、SaveChanges and EF call SQL Statement mixing ( Such as Test2 Method )
/// <summary>
/// Three add statements share the same transaction , Finally using transaction.Commit() Unified submission , All three items were successfully implemented , Affect the database ,
/// If any command fails , The transaction is recycled (Dispose) Will be rolled back automatically , No impact on the database .
/// </summary>
public static void Test1()
{
using (EFDB01Context db = new EFDB01Context())
{
using (var transaction = db.Database.BeginTransaction())
{
try
{
db.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
db.SaveChanges();
db.T_RoleInfor.Add(new T_RoleInfor() {
id = 111, roleName = " Administrators 2", addTime = DateTime.Now }); // Report errors
db.SaveChanges();
string sql1 = @"insert into T_RoleInfor (roleName,roleDescription,addTime) values (@roleName,@roleDescription,@addTime)";
SqlParameter[] pars1 ={
new SqlParameter("@roleName"," Administrators 3"),
new SqlParameter("@roleDescription","txt11"),
new SqlParameter("@addTime",DateTime.Now)
};
db.Database.ExecuteSqlCommand(sql1, pars1);
transaction.Commit();
Console.WriteLine(" succeed ");
}
catch (Exception)
{
Console.WriteLine(" failed ");
}
}
}
}
/// <summary>
/// If not Using Parcel transaction , It needs to be in Catch Medium manual RollBack Roll back
/// </summary>
public static void Test2()
{
using (EFDB01Context db = new EFDB01Context())
{
var transaction = db.Database.BeginTransaction();
try
{
var d1 = new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now };
db.T_RoleInfor.Add(d1);
db.SaveChanges();
db.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 2"+d1.id, addTime = DateTime.Now });
db.SaveChanges();
string sql1 = @"insert into T_RoleInfor (roleName,roleDescription,addTime) values (@roleName,@roleDescription,@addTime)";
SqlParameter[] pars1 ={
new SqlParameter("@roleName"," Administrators 3"),
new SqlParameter("@roleDescription","txt11"),
new SqlParameter("@addTime",DateTime.Now)
};
db.Database.ExecuteSqlCommand(sql1, pars1);
transaction.Commit();
Console.WriteLine(" succeed ");
}
catch (Exception)
{
transaction.Rollback();
Console.WriteLine(" failed ");
}
finally
{
transaction.Dispose();
}
}
}
B. The same database has multiple contexts but “ The same connection ” The business of . One of the contexts starts the transaction , In addition, the context passes through UseTransaction Method to implement shared transactions .
situation ①:
EFDB01Context Directly in OnConfiguring Write a dead connection string in , many times new Context , Such as Test1 Method , Multiple connections , Cannot share transactions .

/// <summary>
/// Situation 1 : stay OnConfiguring Write the connection string in , Create two contexts , Equivalent to two connections , Two connections cannot be connected by using UseTransaction, Establish a transaction connection .
/// I'll report the following error .
/// The specified transaction is not associated with the current connection. Only transactions associated with the current connection may be used.
/// </summary>
public static void Test1()
{
using (EFDB01Context context1 = new EFDB01Context())
{
using (var transaction = context1.Database.BeginTransaction())
{
try
{
context1.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context1.SaveChanges();
using (EFDB01Context context2 = new EFDB01Context())
{
context2.Database.UseTransaction(transaction.GetDbTransaction());
context1.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context1.SaveChanges();
}
// Unified submission
transaction.Commit();
Console.WriteLine(" succeed ");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
situation ②:
EFDB01Context2 adopt public EFDB01Context2(DbContextOptions options) : base(options) This form of constructor , then new When Unified incoming : new DbContextOptionsBuilder().UseSqlServer(new SqlConnection(connectionString)).Options;, To share connections , Such as Test2 Method .

/// <summary>
/// Situation two : Through the parent class constructor
/// </summary>
public static void Test2()
{
var connectionString = "Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
// Take out the connection , To multiple contexts , This is sharing the same connection
var option = new DbContextOptionsBuilder<EFDB01Context2>().UseSqlServer(new SqlConnection(connectionString)).Options;
using (var context1 = new EFDB01Context2(option))
{
using (var transaction = context1.Database.BeginTransaction())
{
try
{
context1.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context1.SaveChanges();
using (var context2 = new EFDB01Context2(option))
{
context2.Database.UseTransaction(transaction.GetDbTransaction());
context1.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context1.SaveChanges();
}
// Unified submission
transaction.Commit();
Console.WriteLine(" succeed ");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
situation ③:
EFDB01Context3 adopt Pass in SqlConnection To realize shared connection , Such as Test3 Method .

public static void Test3()
{
var connectionString = "Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
// Take out the connection , To multiple contexts , This is sharing the same connection
var connection = new SqlConnection(connectionString);
using (var context1 = new EFDB01Context3(connection))
{
using (var transaction = context1.Database.BeginTransaction())
{
try
{
context1.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context1.SaveChanges();
using (var context2 = new EFDB01Context3(connection))
{
context2.Database.UseTransaction(transaction.GetDbTransaction());
context1.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context1.SaveChanges();
}
// Unified submission
transaction.Commit();
Console.WriteLine(" succeed ");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
C. Multiple database technologies transactions in the same database
Such as ADO.Net and EF The common use , Utilization method “UseTransaction” Share the same transaction , Jointly submit . Such as :Test1 Method
/// <summary>
/// ADO.Net and EF A mixture of , Multiple database technologies access the same database
/// </summary>
public static void Test1()
{
var conStr = @"Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
using (var connection=new SqlConnection(conStr))
{
connection.Open();
using (var transaction=connection.BeginTransaction())
{
try
{
//ADO.Net
var command = connection.CreateCommand();
command.Transaction = transaction;
command.CommandText = "DELETE FROM T_RoleInfor";
command.ExecuteNonQuery();
//EF
var options = new DbContextOptionsBuilder<EFDB01Context>().UseSqlServer(connection).Options;
using (var context = new EFDB01Context(options))
{
context.Database.UseTransaction(transaction);
context.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context.SaveChanges();
}
// Comprehensive submission
transaction.Commit();
Console.WriteLine(" succeed ");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
Environmental Affairs (TransactionScope)
1. Usage mode
new TransactionScope Create transaction 、Complete Commit transaction 、 Transaction.Current.Rollback(); Roll back the transaction 、Dispose Destroy object . If you use Using If the package , No more manual Rollback, Walk the Using Will automatically roll back . If not Using Parcel transaction , It needs to be in Catch Medium manual RollBack Roll back , And it's best to do it manually Dispose once .
2. purpose
A. Transactions in the same context .( Multiple SaveChanges( Subsequent use of auto increment primary key )、SaveChanges and EF call SQL Statement mixing )( Such as Test1 Method )
/// <summary>
/// A. Transactions in the same context .( Multiple SaveChanges( Subsequent use of auto increment primary key )、SaveChanges and EF call SQL Statement mixing )
/// </summary>
public static void Test1()
{
using (EFDB01Context1 db = new EFDB01Context1())
{
using (var scope = new TransactionScope(/*TransactionScopeOption.Required, new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }*/))
{
try
{
var data1 = new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now };
db.T_RoleInfor.Add(data1);
db.SaveChanges();
db.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 2" + data1.id, addTime = DateTime.Now }); // Report errors
db.SaveChanges();
string sql1 = @"insert into T_RoleInfor (roleName,roleDescription,addTime) values (@roleName,@roleDescription,@addTime)";
SqlParameter[] pars1 ={
new SqlParameter("@roleName"," Administrators 3"),
new SqlParameter("@roleDescription","txt11"),
new SqlParameter("@addTime",DateTime.Now)
};
db.Database.ExecuteSqlCommand(sql1, pars1);
scope.Complete();
Console.WriteLine(" succeed ");
}
catch (Exception)
{
Console.WriteLine(" failed ");
}
}
}
}
B. Multiple database technologies access transactions in the same database ( Such as Test2 Method )
/// <summary>
/// B. Multiple database technologies access transactions in the same database
/// </summary>
public static void Test2()
{
var conStr = @"Server=localhost;Database=EFDB01;User ID=sa;Password=123456;";
using (var connection = new SqlConnection(conStr))
{
connection.Open();
using (var scope = new TransactionScope())
{
try
{
//ADO.Net
var command = connection.CreateCommand();
command.CommandText = "DELETE FROM T_RoleInfor";
command.ExecuteNonQuery();
//EF
using (var context = new EFDB01Context1())
{
context.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context.SaveChanges();
}
// Comprehensive submission
scope.Complete();
Console.WriteLine(" succeed ");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
C. Multiple different contexts of the same database are supported ( Such as Test3 Method )
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 }
EFDB01Context1
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 }
EFDB01Context2
Run code :
/// <summary>
///C. Two different contexts of the same database are supported
/// </summary>
public static void Test3()
{
using (var scope = new TransactionScope())
{
try
{
using (var context = new EFDB01Context1())
{
context.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context.SaveChanges();
}
using (var context = new EFDB01Context2())
{
context.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context.SaveChanges();
}
// Comprehensive submission
scope.Complete();
Console.WriteLine(" succeed ");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
D. Different database contexts are not supported ,( Such as Test4 Method , Turn on msdtc Service steps : cmd command → net start msdtc , And then I found that there was a mistake :This platform does not support distributed transactions. Explain that at present Core Distributed transactions are not supported on the platform )
Context code :
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 }
dbCore1Context
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 }
EFDB01Context1
Run code :
/// <summary>
///D. Transactions between different databases
/// </summary>
public static void Test4()
{
using (var scope = new TransactionScope())
{
try
{
using (var context = new EFDB01Context1())
{
context.T_RoleInfor.Add(new T_RoleInfor() {
roleName = " Administrators 1", addTime = DateTime.Now });
context.SaveChanges();
}
using (var context = new dbCore1Context())
{
context.UserInfors.Add(new UserInfors() {
id = Guid.NewGuid().ToString("N"), userName = " Administrators 1", userSex = " male " });
context.SaveChanges();
}
// Comprehensive submission
scope.Complete();
Console.WriteLine(" succeed ");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
notes :EF Core Medium System.Transactions The implementation will not include support for distributed transactions , So it can't be used
TransactionScope or CommittableTransaction To coordinate transactions across multiple resource managers . Major distributed transactions need to rely on
Windows Systematic MSDTC service , but .NET Core To achieve cross platform , There is no unified standard for cross platform distributed transactions , The following version hopes to improve .
边栏推荐
- Digital supply chain management system for metallurgical industry: platform lean enterprise management to help the high-quality development of the industry
- 电子元器件行业B2B交易管理系统:提升数据化驱动能力,促进企业销售业绩增长
- IDEA 自动生成单元测试,效率倍增!
- 1.< tag-动态规划和路径组合问题>lt.62. 不同路径 + lt.63. 不同路径 II
- What are the good solutions for industrial control safety of production line
- Grpc security -2: fast implementation of server-side JWT authentication
- APP性能优化之启动流程分析
- Server2022 activation
- Revit API:明细表 ViewSchedule
- Acrel-3000WEB电能管理系统在都巴高速的应用
猜你喜欢

Leetcode——链表笔试题

多门店药品进销存系统源码 大型连锁药店管理系统源码

数字物业管理成趋势,传统物业公司如何通过转型实现数字化蝶变?

fatal: The upstream branch of your current branch does not match the name of your current branch.

点乘和叉乘

Stm32----- timer

推荐4个Flutter重磅开源项目

Cvpr2019/ image translation: transgaga: geometry aware unsupervised image to image translation

PyQt5_ Qtablewidget paging radio right-click menu control

Six complete open source projects, learning enough at a time
随机推荐
Multi store drug inventory system source code large chain drugstore management system source code
APP性能优化之启动流程分析
Idea automatically generates unit tests, doubling efficiency!
This high imitation millet mall project is amazing
Facebook open source shimmer effect
Revit API:明细表 ViewSchedule
【HackTheBox】Fawn
ACM. HJ89 24点运算 ●●●
Server2022 activation
List<? extends T>和List<?super T>区别
多门店药品进销存系统源码 大型连锁药店管理系统源码
The input parameter is object, but it was passed as [object object] because it needs to be converted to JSON format
What are the good solutions for industrial control safety of production line
Some common tool functions in work
Flux in three dimensional vector field
Grpc security -2: fast implementation of server-side JWT authentication
复原IP地址[标准回溯+标准剪枝]
完整开源项目之诗词吧 APP
1.< tag-动态规划和路径组合问题>lt.62. 不同路径 + lt.63. 不同路径 II
Visual explanation of clockwise inner curve in Green's formula hole digging method