28 Stimmen

Wie verwendet man Transaktionen mit dem Entity Framework?

Wenn Sie einen Code wie diesen haben:

Something something = new Something();
BlahEntities b = new BlahEntities()    
b.AddToSomethingSet(something);
b.SaveChanges();

Wie führt man diesen Zusatz innerhalb einer Transaktion aus?

55voto

Kim Major Punkte 3591

Der ObjectContext verfügt über eine Verbindungseigenschaft, die Sie zur Verwaltung von Transaktionen verwenden können.

using (var context = new BlahEntities())
using (var tx = context.BeginTransaction())
{
    // do db stuff here...
    tx.Commit();
}

Im Falle einer Ausnahme wird die Transaktion rückgängig gemacht. Da der Aufruf von BeginTransaction() eine offene Verbindung erfordert, ist es sinnvoll, den Aufruf von BeginTransaction möglicherweise in eine Erweiterungsmethode zu verpacken.

public static DbTransaction BeginTransaction(this ObjectContext context)
{
    if (context.Connection.State != ConnectionState.Open)
    {
        context.Connection.Open();
    }
    return context.Connection.BeginTransaction();
}

Ein Szenario, in dem dieser Ansatz meiner Meinung nach gegenüber TransactionScope nützlich sein könnte, ist, wenn Sie auf zwei Datenquellen zugreifen müssen und nur für eine der Verbindungen Transaktionskontrolle benötigen. Ich denke, dass TransactionScope in diesem Fall zu einer verteilten Transaktion übergehen wird, die möglicherweise nicht erforderlich ist.

3 Stimmen

Dies funktioniert in EF4.1 nicht mehr. Sie müssen Folgendes aufrufen context.Connection.BeginTransaction .

0 Stimmen

@Mikey Cee, es funktioniert, du hast nicht bis zum Ende gelesen - Kim hat die Erweiterungsmethode eingeführt. Kim -- du bist der Mann!!! Du hast mir sehr geholfen, herzlichen Dank.

0 Stimmen

@Kim, vielen Dank für die Unterstützung, das war wirklich hilfreich. Ich möchte jedoch wissen, ob context.Connection.BeginTransaction() zu einer verteilten Transaktion (MSDTC) eskaliert? Ich möchte MSDTC vermeiden, ist das möglich?

26voto

Shiraz Bhaiji Punkte 62129

Sie können Ihren Code innerhalb eines Transaktionsbereichs platzieren

using(TransactionScope scope = new TransactionScope())
{
    // Your code
    scope.Complete(); //  To commit.
}

TransactionScope befindet sich im System.Transactions-Namensraum, der sich in der gleichnamigen Assembly befindet (die Sie möglicherweise manuell zu Ihrem Projekt hinzufügen müssen).

1 Stimmen

Wie ist dies möglich - woher weiß der TransactionScope über den EF-Kontext Bescheid, und/oder umgekehrt?

0 Stimmen

TransActionScope ist eine Art Wrapper für alles, was Sie tun können: msdn.microsoft.com/de-us/library/

15 Stimmen

Seien Sie vorsichtig mit TransactionScope. Es führt Abhängigkeiten von MS DTC ein, die mühsam zu konfigurieren sind und einen hohen Leistungsverlust mit sich bringen. Sobald Sie mehr als eine Transaktion innerhalb von TransactionScope haben, wird eine verteilte Transaktion initiiert. Es handelt sich dann nicht mehr nur um eine einfache DbTransaction, die auf dem verwendeten Provider läuft. Wenn Sie einen anderen Datenbankanbieter als Sql Server verwenden, ist es außerdem wahrscheinlich, dass dieser keine verteilten Transaktionen unterstützt...

9voto

Cylon Cat Punkte 7021

Ich weiß, dass für LINQ to SQL, der Datenkontext eine Transaktion für SubmitChanges() erstellt, wenn es keine vorhandene umgebende Transaktion gibt (TransactionScope ist eine "umgebende" Transaktion). Ich habe nicht gesehen, dass dies für LINQ to Entities dokumentiert ist, aber ich habe Verhalten gesehen, das darauf hindeutet, dass es auch für Entity Framework gilt.

Solange Sie also ein SubmitChanges() (L2SQL) oder SaveChanges() (Linq to Entities) für alle damit zusammenhängenden Änderungen verwenden, sollten Sie ohne TransactionScope auskommen. Sie brauchen einen TransactionScope, wenn

  1. Speichern von mehreren Änderungen mit mehreren SubmitChanges/SaveChanges für eine Transaktion.
  2. Aktualisierung mehrerer Datenquellen innerhalb einer Transaktion (z.B. Linq und ASP.NET membership SQL provider).
  3. Aufrufen anderer Methoden, die ihre eigenen Aktualisierungen vornehmen können.

Ich habe Probleme mit verschachtelten TransactionScopes gehabt. Sie sollen funktionieren, und einfache Testfälle funktionieren, aber wenn ich in den Produktionscode gehe, scheint die "innere" Transaktion dasselbe Objekt zu sein wie die äußere Transaktion. Zu den Symptomen gehören Fehler, die entweder lauten "transaction committed, you can't use this transaction any more" oder "this transaction object has already been disposed". Die Fehler treten in der äußeren Transaktion auf, nachdem die innere Transaktion ihre Arbeit erledigt hat.

1 Stimmen

Danke cyloncat für die ausführliche Beschreibung. Was ich mache, ist, den Datensatz zu erstellen, zu speichern und eine Datei mit der ID des Datensatzes zu erstellen. Erst wenn die Erstellung der Dateien erfolgreich war, gebe ich die Transaktion frei. Macht das Sinn?

0 Stimmen

Ja, das ist ein hervorragendes Beispiel dafür, wann und wie man eine Transaktion verwenden sollte.

2voto

Sabyasachi Mishra Punkte 1597
using System.Transactions;

using (TransactionScope scope = new TransactionScope())
{
    try
    {
        using(DataContext contextObject = new DataContext(ConnectionString))
        {
            contextObject.Connection.Open();
            // First SaveChange method.
            contextObject.SaveChanges();

            // Second SaveChange method.
            contextObject.SaveChanges();
            //--continue to nth save changes

            // If all execution successful
            scope.Complete();   
       }
    }
    catch(Exception ex)
    {
        // If any exception is caught, roll back the entire transaction and end the scope.
        scope.Dispose();
    }
    finally
    {
        // Close the opened connection
        if (contextObject.Connection.State == ConnectionState.Open)
        {
            contextObject.Connection.Close();
        }
    }
}

Ausführliche Erläuterungen finden Sie unter folgendem Link https://msdn.microsoft.com/en-us/data/dn456843.aspx

0voto

Mesut Talebi2 Punkte 23

In allen Versionen von Entity Framework wird bei jeder Ausführung von SaveChanges() zum Einfügen, Aktualisieren oder Löschen in der Datenbank diese Operation in eine Transaktion verpackt. Diese Transaktion dauert nur lange genug, um die Operation auszuführen und wird dann beendet. Wenn Sie eine weitere solche Operation ausführen, wird eine neue Transaktion gestartet. Für die neueste Entity Framework Version: 6.0 +

Lesen Sie hier mehr: EntityFramework und Transaktion

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X