深入分析EF Core事務(wù)提交,分布式事務(wù)
作者:conan
雖然所有關(guān)系數(shù)據(jù)庫提供程序都支持事務(wù),但在調(diào)用事務(wù) API 時,可能會引發(fā)其他提供程序類型或不執(zhí)行任何操作。
本文轉(zhuǎn)載自微信公眾號「后端Q」,作者conan。轉(zhuǎn)載本文請聯(lián)系后端Q公眾號。
控制事務(wù)
可以使用 DbContext.Database API 開始、提交和回滾事務(wù)。 以下示例顯示了在單個事務(wù)中執(zhí)行的兩個 SaveChanges 操作以及一個 LINQ 查詢:
- using var context = new BloggingContext();
- using var transaction = context.Database.BeginTransaction();
- try
- {
- context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
- context.SaveChanges();
- context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
- context.SaveChanges();
- var blogs = context.Blogs
- .OrderBy(b => b.Url)
- .ToList();
- // Commit transaction if all commands succeed, transaction will auto-rollback
- // when disposed if either commands fails
- transaction.Commit();
- }
- catch (Exception)
- {
- // TODO: Handle failure
- }
雖然所有關(guān)系數(shù)據(jù)庫提供程序都支持事務(wù),但在調(diào)用事務(wù) API 時,可能會引發(fā)其他提供程序類型或不執(zhí)行任何操作。
使用 System.Transactions
如果需要跨較大作用域進(jìn)行協(xié)調(diào),則可以使用環(huán)境事務(wù)。
- using (var scope = new TransactionScope(
- TransactionScopeOption.Required,
- new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
- {
- using var connection = new SqlConnection(connectionString);
- connection.Open();
- try
- {
- // Run raw ADO.NET command in the transaction
- var command = connection.CreateCommand();
- command.CommandText = "DELETE FROM dbo.Blogs";
- command.ExecuteNonQuery();
- // Run an EF Core command in the transaction
- var options = new DbContextOptionsBuilder<BloggingContext>()
- .UseSqlServer(connection)
- .Options;
- using (var context = new BloggingContext(options))
- {
- context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
- context.SaveChanges();
- }
- // Commit transaction if all commands succeed, transaction will auto-rollback
- // when disposed if either commands fails
- scope.Complete();
- }
- catch (Exception)
- {
- // TODO: Handle failure
- }
- }
還可以在顯式事務(wù)中登記。
- using (var transaction = new CommittableTransaction(
- new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted }))
- {
- var connection = new SqlConnection(connectionString);
- try
- {
- var options = new DbContextOptionsBuilder<BloggingContext>()
- .UseSqlServer(connection)
- .Options;
- using (var context = new BloggingContext(options))
- {
- context.Database.OpenConnection();
- context.Database.EnlistTransaction(transaction);
- // Run raw ADO.NET command in the transaction
- var command = connection.CreateCommand();
- command.CommandText = "DELETE FROM dbo.Blogs";
- command.ExecuteNonQuery();
- // Run an EF Core command in the transaction
- context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
- context.SaveChanges();
- context.Database.CloseConnection();
- }
- // Commit transaction if all commands succeed, transaction will auto-rollback
- // when disposed if either commands fails
- transaction.Commit();
- }
- catch (Exception)
- {
- // TODO: Handle failure
- }
- }
System.Transactions 的限制
- EF Core 依賴數(shù)據(jù)庫提供程序以實現(xiàn)對 System.Transactions 的支持。 如果提供程序未實現(xiàn)對 System.Transactions 的支持,則可能會完全忽略對這些 API 的調(diào)用。 SqlClient 支持它。
- 自 .NET Core 2.1 起,System.Transactions 實現(xiàn)不包括對分布式事務(wù)的支持,因此不能使用 TransactionScope 或 CommittableTransaction 來跨多個資源管理器協(xié)調(diào)事務(wù)。
責(zé)任編輯:武曉燕
來源:
后端Q