Mit EF6 haben Sie eine neue Transaktion, die wie folgt verwendet werden kann:
using (var context = new PostEntityContainer())
{
using (var dbcxtransaction = context.Database.BeginTransaction())
{
try
{
PostInformation NewPost = new PostInformation()
{
PostId = 101,
Content = "This is my first Post related to Entity Model",
Title = "Transaction in EF 6 beta"
};
context.Post_Details.Add(NewPost);
context.SaveChanges();
PostAdditionalInformation PostInformation = new PostAdditionalInformation()
{
PostId = (101),
PostName = "Working With Transaction in Entity Model 6 Beta Version"
};
context.PostAddtional_Details.Add(PostInformation);
context.SaveChanges();
dbcxtransaction.Commit();
}
catch
{
dbcxtransaction.Rollback();
}
}
}
Wird ein Rollback tatsächlich benötigt, wenn die Dinge seitwärts gehen? Ich bin neugierig, weil in der Commit-Beschreibung steht: "Commit die zugrunde liegende Store-Transaktion."
In der Rollback-Beschreibung heißt es: "Rollt die zugrunde liegende Geschäftstransaktion zurück."
Das macht mich neugierig, denn es sieht so aus, als würden die zuvor ausgeführten Befehle nicht gespeichert, wenn Commit nicht aufgerufen wird (was mir logisch erscheint). Aber wenn dies der Fall ist, was wäre der Grund, die Rollback-Funktion aufzurufen? In EF5 habe ich TransactionScope verwendet, das keine Rollback-Funktion (nur eine vollständige) hatte, was mir logisch erschien. Aus MS-DTC-Gründen kann ich das TransactionScope nicht mehr verwenden, aber ich kann auch keinen Try-Catch wie im obigen Beispiel verwenden (dh ich benötige nur das Commit).
quelle
SaveChanges
nur einmal hinzuzufügen ).Antworten:
Sie müssen nicht
Rollback
manuell aufrufen, da Sie dieusing
Anweisung verwenden.DbContextTransaction.Dispose
Methode wird am Ende desusing
Blocks aufgerufen . Die Transaktion wird automatisch zurückgesetzt, wenn die Transaktion nicht erfolgreich festgeschrieben wurde (keine aufgerufenen oder aufgetretenen Ausnahmen). Es folgt der Quellcode derSqlInternalTransaction.Dispose
Methode (DbContextTransaction.Dispose
wird bei Verwendung des SqlServer-Anbieters endgültig an ihn delegiert):private void Dispose(bool disposing) { // ... if (disposing && this._innerConnection != null) { this._disposing = true; this.Rollback(); } }
Sie sehen, es prüft, ob
_innerConnection
nicht null ist. Wenn nicht, wird die Transaktion zurückgesetzt (wenn festgeschrieben,_innerConnection
ist sie null). Mal sehen, wasCommit
macht:internal void Commit() { // Ignore many details here... this._innerConnection.ExecuteTransaction(...); if (!this.IsZombied && !this._innerConnection.IsYukonOrNewer) { // Zombie() method will set _innerConnection to null this.Zombie(); } else { this.ZombieParent(); } // Ignore many details here... } internal void Zombie() { this.ZombieParent(); SqlInternalConnection innerConnection = this._innerConnection; // Set the _innerConnection to null this._innerConnection = null; if (innerConnection != null) { innerConnection.DisconnectTransaction(this); } }
quelle
Solange Sie immer SQL Server mit EF verwenden, müssen Sie den catch nicht explizit verwenden, um die Rollback-Methode aufzurufen. Das automatische Zurücksetzen des using-Blocks bei Ausnahmen funktioniert immer.
Wenn Sie jedoch aus der Sicht von Entity Framework darüber nachdenken, können Sie sehen, warum alle Beispiele den expliziten Aufruf zum Rollback der Transaktion verwenden. Für den EF ist der Datenbankanbieter beliebig und steckbar, und der Anbieter kann durch MySQL oder eine andere Datenbank mit einer EF-Anbieterimplementierung ersetzt werden. Aus EF-Sicht gibt es daher keine Garantie dafür, dass der Anbieter die veräußerte Transaktion automatisch zurücksetzt, da der EF nichts über die Implementierung des Datenbankanbieters weiß.
In der EF-Dokumentation wird daher als bewährte Methode empfohlen, ein explizites Rollback durchzuführen - für den Fall, dass Sie eines Tages den Anbieter auf eine Implementierung umstellen, die bei der Entsorgung kein automatisches Rollback durchführt.
Meiner Meinung nach wird jeder gute und gut geschriebene Anbieter die Transaktion in der Dispose automatisch zurücksetzen, so dass der zusätzliche Aufwand, alles innerhalb des using-Blocks mit einem Try-Catch-Rollback zu verpacken, übertrieben ist.
quelle
quelle