Verwenden Sie die gleichen Transaktion in verschiedenen Methoden, mit Entity Framework-Core

BEARBEITEN (02/03/2018) : Seit Entity Framework Core 2.1, EF-Core implementiert Transaktionen, cross-Kontext-Transaktionen, ambient-Transaktionen und Transaktionen, die Bereiche also, diese Frage ist jetzt veraltet.

Dies ist die offizielle Dokumentation über die Transaktionen in EF Kern : https://docs.microsoft.com/en-us/ef/core/saving/transactions.


Wie kann ich mit der gleichen Transaktion in verschiedenen Methoden ? Das Ziel ist, können commit-oder rollback alle änderungen, wenn ein Fehler aufgetreten ist.

Ich bin mit Entity Framework-Core-version 1.1.0-preview1-final, und SQL Server 2014.

Ich habe zum Beispiel ein Entity Framework Datenbank-Kontext :

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; }
    }

Und ich habe zwei Klassen, die den Umgang mit Daten, die beide mit dem gleichen Kontext :

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;
            }
        }
    }
}

In meine business-Logik, ich habe einen Dienst, und ich möchte Sie zum aufrufen der Methode void Erstellen(Guid-Schlüssel) auf mein erstes repository, dann die gleiche Methode, die von meiner zweiten repository und verpflichten nur, wenn die beiden traten ohne Fehler (wenn ein Fehler aufgetreten ist, in der zweiten Methode, ich möchte rollback commit in der ersten Methode).

Wie kann ich das tun ? Was ist die beste Praxis mit Entity Framework-Kern und Transaktionen ?

Ich habe versucht, verschiedene Dinge, wie dieses, aber es nie funktioniert (mit dieser Methode habe ich den Fehler ) :

Warning als error-Ausnahme ausgelöst, für die Warnung
'RelationalEventId.AmbientTransactionWarning': Eine ambient-Transaktion
erkannt wurde. Entity Framework Core nicht unterstützt ambient
Transaktionen.

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;
                }
            }
        }
}

Ich die Dokumentation zu Lesen, besonders diese Seite ( https://docs.microsoft.com/en-us/ef/core/saving/transactions ), aber ich habe nicht die Methode UseTransaction auf Microsoft.EntityFrameworkCore.Infrastruktur.DatabaseFacade.

  • Nach mehr Forschung, ich glaube nicht, dass es möglich ist mit der aktuellen version von Entity Framework Core : github.com/dotnet/corefx/issues/12534 . Es scheint für die nächste version geplant
InformationsquelleAutor AdrienTorris | 2016-11-15
Schreibe einen Kommentar