当前位置:网站首页>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 .
边栏推荐
- 2022年信息安全工程師考試知識點:訪問控制
- PMP考试相关计算公式汇总!考前必看
- [proteus simulation] example of T6963C driving pg12864 (with Chinese and English display)
- Avoid confusion when switching between arouter components
- log Network Execution Time
- 点乘和叉乘
- Total number of combinations ii[each element can only be solved by + once]
- 生成所有可能的二叉搜索树
- Six complete open source projects, learning enough at a time
- 推荐4个Flutter重磅开源项目
猜你喜欢

产线工控安全有什么好的解决方案

CVPR2019/图像翻译:TransGaGa: Geometry-Aware Unsupervised Image-to-Image Translation几何感知的无监督图像到图像的翻译

A person even ran a Weibo app

6 大完整开源项目,一次学个够

Facebook open source shimmer effect

高仿书旗小说 Flutter 版,学起来

The lower left corner of vs QT VTK displays the synchronized minor coordinate axis

开口式霍尔电流传感器助力直流配电改造

老龄化下背景下,综合能效管理平台为医院保驾护航
![组合总数II[每个元素只能用一次 + 去重复解集]](/img/06/a40e28a1882a4278883202bc9c72d3.png)
组合总数II[每个元素只能用一次 + 去重复解集]
随机推荐
Niuke.com: the double pointer problem of receiving rainwater
Postman返回值中文乱码????
1004. number of maximum consecutive 1 III ●●
log Network Execution Time
产线工控安全有什么好的解决方案
再来一个高仿开眼的短视频APP
三款很酷很骚气的底部导航
What is the same origin policy?
Multi store drug inventory system source code large chain drugstore management system source code
Thinking (86): master-slave realization idea
2018/GAN:Self-Attention Generative Adversarial Networks自我注意生成对抗网络
E: Unable to acquire lock /var/lib/dpkg/lock
IDEA 自动生成单元测试,效率倍增!
matlab实现对图像批量重命名
Docker deploy redis
Embedded interface review materials
MySQL导致索引失效的情况详解
电子元器件行业B2B交易管理系统:提升数据化驱动能力,促进企业销售业绩增长
老龄化下背景下,综合能效管理平台为医院保驾护航
Acrel-3000WEB电能管理系统在都巴高速的应用