EF Core事务提交,分布式事务

控制事务

可以使用 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 fails    transaction.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 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    }}

还可以在显式事务中登记。

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 的限制

  1. EF Core 依赖数据库提供程序以实现对 System.Transactions 的支持。 如果提供程序未实现对 System.Transactions 的支持,则可能会完全忽略对这些 API 的调用。 SqlClient 支持它。

  2. 自 .NET Core 2.1 起,System.Transactions 实现不包括对分布式事务的支持,因此不能使用 TransactionScope 或 CommittableTransaction 来跨多个资源管理器协调事务。