当前位置:网站首页>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 .
边栏推荐
- Unity Text组件空格换行问题
- Image segmentation - data annotation
- Server2022 activation
- 高仿斗鱼 APP
- One person even broke up a Netease cloud music Cloud Village
- 2018/gan:self attention generating adversarial networks
- Facebook open source shimmer effect
- Leetcode——链表笔试题
- 多门店药品进销存系统源码 大型连锁药店管理系统源码
- Generate all possible binary search trees
猜你喜欢
![Total number of combinations ii[each element can only be solved by + once]](/img/06/a40e28a1882a4278883202bc9c72d3.png)
Total number of combinations ii[each element can only be solved by + once]

Taylor formula and common expansion

再来一个高仿开眼的短视频APP

smart-doc + Torna 兼容版本

Notepad++实用功能分享(正则行尾行首替换常用方法、文本比对功能等)

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

Golang type assertion

19 MySQL optimizations commonly used in projects

Image segmentation - data annotation

2018/GAN:Self-Attention Generative Adversarial Networks自我注意生成对抗网络
随机推荐
Grpc security -2: fast implementation of server-side JWT authentication
产线工控安全有什么好的解决方案
Avoid confusion when switching between arouter components
High imitation Betta app
Classical Chinese can be programmed???
1004. number of maximum consecutive 1 III ●●
工作中一些常用的工具函数
推荐4个Flutter重磅开源项目
电子元器件行业B2B交易管理系统:提升数据化驱动能力,促进企业销售业绩增长
2022年信息安全工程師考試知識點:訪問控制
2022山东健博会,济南国际大健康产业博览会,中国营养健康展
接私活必备的 6 个开源项目
docker redis集群配置
ACM. HJ89 24点运算 ●●●
高仿書旗小說 Flutter 版,學起來
牛客网:接雨水的双指针问题
fatal: The upstream branch of your current branch does not match the name of your current branch.
List<? extends T>和List<?super T>区别
Loop caused by add of sublist in list
Setting method of bar code local segment data variable