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
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ein möglicher Ansatz ist der Einsatz einer middleware und stellen Sie Ihre Logik für begin/commit/rollback gibt. Zum Beispiel, am Anfang jeder Anfrage, beginnen Sie eine Transaktion auf der zugrunde liegenden Datenbank-Verbindung. Am Ende der Anfrage commit oder rollback die Transaktion. Da Sie vermutlich auch die Verwendung von single context-Instanz pro Anfrage, das würde Ihr problem lösen. Zusätzlich extrahiert dieses Anliegen aus Ihrem repository/service-Klassen.
Hier ein Beispiel-code, den Sie vielleicht verwenden Sie als ein Start. Habe es noch nicht getestet in realen Szenarios zwar:
Dann in Ihre
Startup.Configure()
Methode:BEARBEITEN (02/03/2018) : Seit Entity Framework Core 2.1 verwenden, können Sie Transaktionen, cross-Kontext-Transaktionen, ambient-Transaktionen und Transaktionen Bereiche, so dass Sie nicht haben, um zu implementieren ein work-around.
Dies ist die offizielle Dokumentation : https://docs.microsoft.com/en-us/ef/core/saving/transactions.
Habe ich endlich eine Lösung gefunden, wartet die nächste Version des Entity Framework-Kern, der die Lage versetzen wird, verwenden Sie die Transaktion Bereiche und ambient-Transaktionen.
Als die db-Transaktion ist mit einer Datenbank verknüpft Kontext, und der Kontext der Datenbank ist das gleiche in alle meine Daten auf Klassen (vielen Dank dependency injection), wenn ich starten Sie die Transaktion in einem Prozess, es wird geteilt werden von anderen Daten, die auf Klassen in den gleichen Prozess, bis die Transaktion abgegeben werden sollen (ich hatte ein upgrade meiner Entity Framework-Kern auf 1.1.0-preview1-Finale zu haben Einweg-Transaktionen).
Konkret, ich hatte eine Klasse zum Umgang mit Transaktionen :
Ist und ich diese Klasse verwenden, wie dies in meine Dienste :
einmal entity framework selbst wickeln jede Anfrage als Transaktion, können Sie vermeiden, explizite Transaktionen und explizite "saveChanges", und u erhalten, alle request commit oder rollbacked atomar