在Entity Framework Core的不同方法中使用相同的事務

asp.net-core-1.0 c# entity-framework-core sql-server-2014-express transactions

編輯(02/03/2018):自Entity Framework Core 2.1以來,EF Core實現了事務,跨上下文事務,環境事務和事務範圍,因此這個問題現已過時。

這是關於EF Core中交易的官方文檔: https//docs.microsoft.com/en-us/ef/core/saving/transactions


如何在不同的方法中使用相同的事務?目標是在發生錯誤時提交或回滾所有修改。

我正在使用Entity Framework Core版本1.1.0-preview1-finalSQL Server 2014。

例如,我有一個Entity Framework數據庫上下文:

public class ApplicationDatabaseContext : DbContext
    {
        public ApplicationDatabaseContext(DbContextOptions<ApplicationDatabaseContext> options)
           : base(options)
        { }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<TransactionLog1>(entity =>
            {
                entity.ToTable("TRANSACTION_LOG_1");

                entity.Property(e => e.CreationDate)
                    .HasColumnType("datetime")
                    .HasDefaultValueSql("getdate()");
            });

            modelBuilder.Entity<TransactionLog2>(entity =>
            {
                entity.ToTable("TRANSACTION_LOG_2");

                entity.Property(e => e.CreationDate)
                    .HasColumnType("datetime")
                    .HasDefaultValueSql("getdate()");
            });
        }

        public virtual DbSet<TransactionLog1> TransactionLog1 { get; set; }
        public virtual DbSet<TransactionLog2> TransactionLog2 { get; set; }
    }

我有兩個類來處理數據,兩者都使用相同的上下文:

public interface IRepository1
{
    void Create(Guid key);
}

public sealed class Repository1 : IRepository1
{
    private readonly ApplicationDatabaseContext _dbContext;

    public Repository1(ApplicationDatabaseContext dbcontext)
    {
        _dbContext = dbcontext;
    }

    public void Create(Guid key)
    {
        using (_dbContext.Database.BeginTransaction())
        {
            try
            {
                _dbContext.TransactionLog1.Add(new TransactionLog1 { Key = key });
                _dbContext.SaveChanges();

                _dbContext.Database.CommitTransaction();
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}

public interface IRepository2
{
    void Create(Guid key);
}

public sealed class Repository2 : IRepository2
{
    private readonly ApplicationDatabaseContext _dbContext;

    public Repository2(ApplicationDatabaseContext dbcontext)
    {
        _dbContext = dbcontext;
    }

    public void Create(Guid key)
    {
        using (_dbContext.Database.BeginTransaction())
        {
            try
            {
                _dbContext.TransactionLog2.Add(new TransactionLog2 { Key = key });
                _dbContext.SaveChanges();

                _dbContext.Database.CommitTransaction();
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}

在我的業務邏輯中,我有一個服務,我想在我的第一個存儲庫上調用方法void Create(Guid key) ,然後從我的第二個存儲庫調用相同的方法,並且只有在兩者都沒有錯誤的情況下才會提交(如果發生任何錯誤)在secon方法中,我想回滾在第一個方法中完成的提交)。

我怎樣才能做到這一點 ? Entity Framework Core和交易的最佳實踐是什麼?

我試過幾件事,比如這樣,但它永遠不會有效(用這種方法我有錯誤):

作為警告'RelationalEventId.AmbientTransactionWarning'的錯誤異常警告:已檢測到環境事務。實體框架核心不支持環境事務。

public sealed class Service3 : IService3
{
        private readonly IRepository1 _repo1;
        private readonly IRepository2 _repo2;

        public Service3(IRepository1 repo1, IRepository2 repo2)
        {
            _repo1 = repo1;
            _repo2 = repo2;
        }

        public void Create(Guid key)
        {
            using (TransactionScope scope = new TransactionScope())
            {
                try
                {
                    _repo1.Create(key);
                    _repo2.Create(key);

                    scope.Complete();
                }
                catch (Exception)
                {
                    throw;
                }
            }
        }
}

我閱讀了文檔,特別是這個頁面( https://docs.microsoft.com/en-us/ef/core/saving/transactions ),但我沒有在Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade上使用 UseTransaction方法。

熱門答案

編輯(02/03/2018):自實體框架核心2.1以來,您可以使用事務,跨上下文事務,環境事務和事務範圍,因此您不必實現解決方法。

這是官方文檔: https//docs.microsoft.com/en-us/ef/core/saving/transactions


我終於找到了一個等待下一個Entity Framework Core版本的解決方案,它將支持使用事務範圍和環境事務。

由於db事務與數據庫上下文相關,並且數據庫上下文在我的所有數據訪問類中都是相同的(感謝依賴注入),當我在進程中啟動事務時,它將被其他數據訪問類共享。在處理交易之前的同一過程(我必須將我的Entity Framework Core升級到1.1.0-preview1-final以進行一次性交易)。

具體來說,我有一個類來處理交易:

public interface ITransactionDealerRepository
{
    void BeginTransaction();

    void CommitTransaction();

    void RollbackTransaction();

    void DisposeTransaction();
}

public sealed class TransactionDealerRepository : BaseEntityFrameworkRepository, ITransactionDealerRepository
{
    public TransactionDealerRepository(MyDBContext dbContext)
       : base(dbContext)
    { }

    public void BeginTransaction()
    {
        _dbContext.Database.BeginTransaction();
    }

    public void CommitTransaction()
    {
        _dbContext.Database.CommitTransaction();
    }

    public void RollbackTransaction()
    {
        _dbContext.Database.RollbackTransaction();
    }

    public void DisposeTransaction()
    {
        _dbContext.Database.CurrentTransaction.Dispose();
    }
}

我在我的服務中使用這個類:

    public void Create(Guid key)
    {
        _transactionProvider.BeginTransaction();

        try
        {
            _repo1.Create(key);
            _repo2.Create(key);

            _transactionProvider.CommitTransaction();
        }
        catch (Exception)
        {
            _transactionProvider.RollbackTransaction();
            throw;
        }
        finally
        {
            _transactionProvider.DisposeTransaction();
        }
    }


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因