控制事务
可以使用 DbContext.Database
API 开始、提交和回滚事务。 以下示例显示了在单个事务中执行的两个 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 failstransaction.Commit();
}
catch (Exception)
{// TODO: Handle failure
}
虽然所有关系数据库提供程序都支持事务,但在调用事务 API 时,可能会引发其他提供程序类型或不执行任何操作。
使用 System.Transactions
如果需要跨较大作用域进行协调,则可以使用环境事务。
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 transactionvar command = connection.CreateCommand();command.CommandText = "DELETE FROM dbo.Blogs";command.ExecuteNonQuery();// Run an EF Core command in the transactionvar 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 failsscope.Complete();}catch (Exception){// TODO: Handle failure}
}
还可以在显式事务中登记。
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 transactionvar command = connection.CreateCommand();command.CommandText = "DELETE FROM dbo.Blogs";command.ExecuteNonQuery();// Run an EF Core command in the transactioncontext.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 failstransaction.Commit();}catch (Exception){// TODO: Handle failure}
}
System.Transactions 的限制
EF Core 依赖数据库提供程序以实现对 System.Transactions 的支持。 如果提供程序未实现对 System.Transactions 的支持,则可能会完全忽略对这些 API 的调用。 SqlClient 支持它。
自 .NET Core 2.1 起,System.Transactions 实现不包括对分布式事务的支持,因此不能使用
TransactionScope
或CommittableTransaction
来跨多个资源管理器协调事务。