Transactions oder SaveChanges (false) und AcceptAllChanges () verwenden?

c# entity-framework transactions

Frage

Ich habe Transaktionen untersucht und es scheint, dass sie sich in EF um sich selbst kümmern, solange ich false an SaveChanges() und AcceptAllChanges() aufrufen AcceptAllChanges() wenn keine Fehler AcceptAllChanges() :

SaveChanges(false);
// ...
AcceptAllChanges();

Was ist, wenn etwas schief geht? Muss ich nicht zurückrollen, oder sobald meine Methode den Gültigkeitsbereich verlässt, ist die Transaktion beendet?

Was passiert mit allen Spalten, die während der Transaktion zugewiesen wurden? Ich nehme an, wenn jemand anderes nach meinem einen Datensatz hinzugefügt hat, bevor der Wert für mich schlecht war, bedeutet dies, dass ein fehlender Identitätswert vorhanden ist.

Gibt es einen Grund, die Standard- TransactionScope Klasse in meinem Code zu verwenden?

Akzeptierte Antwort

Beim Entity Framework ist meistens SaveChanges() ausreichend. Dadurch wird eine Transaktion erstellt oder in eine Ambient-Transaktion eingetragen und alle notwendigen Arbeiten in dieser Transaktion ausgeführt.

Manchmal ist das SaveChanges(false) + AcceptAllChanges() Pairing jedoch hilfreich.

Der nützlichste Ort dafür ist in Situationen, in denen Sie eine verteilte Transaktion in zwei verschiedenen Kontexten durchführen möchten.

Dh so etwas (schlecht):

using (TransactionScope scope = new TransactionScope())
{
    //Do something with context1
    //Do something with context2

    //Save and discard changes
    context1.SaveChanges();

    //Save and discard changes
    context2.SaveChanges();

    //if we get here things are looking good.
    scope.Complete();
}

Wenn context1.SaveChanges() erfolgreich ist, context2.SaveChanges() fehlschlägt, wird die gesamte verteilte Transaktion abgebrochen. Leider hat das Entity Framework die Änderungen in context1 bereits verworfen, sodass Sie den Fehler nicht wiederholen oder protokollieren können.

Wenn Sie jedoch Ihren Code so ändern, dass er so aussieht:

using (TransactionScope scope = new TransactionScope())
{
    //Do something with context1
    //Do something with context2

    //Save Changes but don't discard yet
    context1.SaveChanges(false);

    //Save Changes but don't discard yet
    context2.SaveChanges(false);

    //if we get here things are looking good.
    scope.Complete();
    context1.AcceptAllChanges();
    context2.AcceptAllChanges();

}

Während der Aufruf von SaveChanges(false) die erforderlichen Befehle an die Datenbank sendet, wird der Kontext selbst nicht geändert. Sie können ihn also bei Bedarf erneut ausführen oder den ObjectStateManager abfragen, wenn Sie möchten.

Dies bedeutet, wenn die Transaktion tatsächlich eine Ausnahme auslöst, die Sie kompensieren können, indem Sie den Status der einzelnen ObjectStateManager Kontexte entweder erneut versuchen oder protokollieren.

Sehen Sie meinen Blogeintrag für mehr.


Beliebte Antwort

Wenn Sie EF6 (Entity Framework 6+) verwenden, hat sich dies für Datenbankaufrufe in SQL geändert.
Siehe: http://msdn.microsoft.com/de-de/data/dn456843.aspx

Verwenden Sie context.Database.BeginTransaction.

Von MSDN:

using (var context = new BloggingContext()) 
{ 
    using (var dbContextTransaction = context.Database.BeginTransaction()) 
    { 
        try 
        { 
            context.Database.ExecuteSqlCommand( 
                @"UPDATE Blogs SET Rating = 5" + 
                    " WHERE Name LIKE '%Entity Framework%'" 
                ); 

            var query = context.Posts.Where(p => p.Blog.Rating >= 5); 
            foreach (var post in query) 
            { 
                post.Title += "[Cool Blog]"; 
            } 

            context.SaveChanges(); 

            dbContextTransaction.Commit(); 
        } 
        catch (Exception) 
        { 
            dbContextTransaction.Rollback(); //Required according to MSDN article 
            throw; //Not in MSDN article, but recommended so the exception still bubbles up
        } 
    } 
} 


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum