Frage

Eines der Dinge, die mich völlig verwirren, ist die Verwendung von session.Flush,in Verbindung mit session.Commit, Und session.Close.

Manchmal session.Close funktioniert, z. B. werden alle Änderungen übernommen, die ich benötige.Ich weiß, dass ich Commit verwenden muss, wenn ich eine Transaktion oder eine Arbeitseinheit mit mehreren Erstellungs-/Aktualisierungs-/Löschvorgängen habe, damit ich bei Auftreten eines Fehlers ein Rollback durchführen kann.

Aber manchmal verwirrt mich die Logik dahinter wirklich session.Flush.Ich habe Beispiele gesehen, bei denen Sie eine haben session.SaveOrUpdate() gefolgt von einem Flush, aber wenn ich Flush entferne, funktioniert es trotzdem einwandfrei.Manchmal stoße ich auf Fehler in der Flush-Anweisung, die besagen, dass die Sitzung abgelaufen ist, und durch das Entfernen wurde sichergestellt, dass dieser Fehler nicht auftritt.

Hat jemand eine gute Richtlinie, wo und wann man einen Flush verwenden sollte?Ich habe mir dazu die NHibernate-Dokumentation angesehen, kann aber immer noch keine eindeutige Antwort finden.

War es hilfreich?

Lösung

Knapp:

  1. Verwenden Sie immer Transaktionen
  2. Nicht verwenden Close(), wickeln Sie Ihre Anrufe stattdessen auf ein ISession in einem using Aussage bzw Verwalten Sie den Lebenszyklus Ihrer ISession woanders.

Aus die Dokumentation:

Von Zeit zu Zeit ISession führt die erforderlichen SQL-Anweisungen aus, um den Status der ADO.NET-Verbindung mit dem Status der im Speicher gehaltenen Objekte zu synchronisieren.Dieser Vorgang, Flush, findet standardmäßig an den folgenden Punkten statt

  • aus einigen Aufrufen von Find() oder Enumerable()
  • aus NHibernate.ITransaction.Commit()
  • aus ISession.Flush()

Die SQL-Anweisungen werden in der folgenden Reihenfolge ausgegeben

  1. alle Entitätseinfügungen in derselben Reihenfolge, in der die entsprechenden Objekte gespeichert wurden ISession.Save()
  2. alle Entitätsaktualisierungen
  3. alle Sammlungslöschungen
  4. alle Löschungen, Aktualisierungen und Einfügungen von Sammlungselementen
  5. alle Sammlungseinfügungen
  6. Alle Entitätslöschungen in derselben Reihenfolge, in der die entsprechenden Objekte gelöscht wurden ISession.Delete()

(Eine Ausnahme besteht darin, dass Objekte mit nativer ID-Generierung beim Speichern eingefügt werden.)

Außer wenn Sie dies ausdrücklich tun Flush(), gibt es keinerlei Garantien dafür, wann die Sitzung die ADO.NET-Aufrufe ausführt, sondern nur für die Reihenfolge, in der sie ausgeführt werden.NHibernate garantiert jedoch, dass die ISession.Find(..) Methoden geben niemals veraltete Daten zurück;Sie werden auch nicht die falschen Daten zurückgeben.

Es ist möglich, das Standardverhalten so zu ändern, dass die Spülung seltener erfolgt.Der FlushMode Die Klasse definiert drei verschiedene Modi:nur zum Commit-Zeitpunkt leeren (und nur, wenn die NHibernate ITransaction API verwendet wird), automatisch mit der erläuterten Routine leeren oder nie leeren, es sei denn Flush() wird explizit aufgerufen.Der letzte Modus ist nützlich für Arbeitseinheiten mit langer Laufzeit, bei denen ein ISession wird für längere Zeit offen gehalten und abgeklemmt.

...

Siehe auch diese Abteilung:

Das Beenden einer Sitzung umfasst vier verschiedene Phasen:

  • Spülen Sie die Sitzung
  • die Transaktion festschreiben
  • Schließen Sie die Sitzung
  • Ausnahmen behandeln

Leeren der Sitzung

Wenn Sie zufällig das verwenden ITransaction API, Sie müssen sich über diesen Schritt keine Gedanken machen.Dies wird implizit ausgeführt, wenn die Transaktion festgeschrieben wird.Ansonsten solltest du anrufen ISession.Flush() um sicherzustellen, dass alle Änderungen mit der Datenbank synchronisiert werden.

Festschreiben der Datenbanktransaktion

Wenn Sie die NHibernate ITransaction API verwenden, sieht dies so aus:

tx.Commit(); // flush the session and commit the transaction

Wenn Sie ADO.NET-Transaktionen selbst verwalten, sollten Sie dies manuell tun Commit() die ADO.NET-Transaktion.

sess.Flush();
currentTransaction.Commit();

Wenn Sie sich entscheiden, Ihre Änderungen nicht zu übernehmen:

tx.Rollback();  // rollback the transaction

oder:

currentTransaction.Rollback();

Wenn Sie die Transaktion zurücksetzen, sollten Sie die aktuelle Sitzung sofort schließen und verwerfen, um sicherzustellen, dass der interne Status von NHibernate konsistent ist.

Schließen der ISession

Ein Aufruf an ISession.Close() markiert das Ende einer Sitzung.Die Hauptauswirkung von Close() besteht darin, dass die ADO.NET-Verbindung von der Sitzung getrennt wird.

tx.Commit();
sess.Close();

sess.Flush();
currentTransaction.Commit();
sess.Close();

Wenn Sie Ihren eigenen Anschluss bereitgestellt haben, Close() gibt einen Verweis darauf zurück, sodass Sie es manuell schließen oder an den Pool zurückgeben können.Ansonsten Close() gibt es an den Pool zurück.

Andere Tipps

Ab NHibernate 2.0 sind Transaktionen für DB-Vorgänge erforderlich.deshalb, die ITransaction.Commit() Der Anruf übernimmt die erforderliche Spülung.Wenn Sie aus irgendeinem Grund keine NHibernate-Transaktionen verwenden, erfolgt kein automatisches Leeren der Sitzung.

Von Zeit zu Zeit führt die ISession die erforderlichen SQL-Anweisungen aus, um den Status der ADO.NET-Verbindung mit dem Status der im Speicher gehaltenen Objekte zu synchronisieren.

Und immer verwenden

 using (var transaction = session.BeginTransaction())
 {
     transaction.Commit();
 }

Nachdem die Änderungen festgeschrieben wurden, verwenden wir zum Speichern dieser Änderungen in der Datenbank „transaction.Commit();“

Hier sind zwei Beispiele meines Codes, bei dem er ohne session.Flush() fehlschlagen würde:

http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html

Am Ende sehen Sie einen Codeabschnitt, in dem ich die Identitätseinfügung aktiviert, die Entität speichere, sie dann leere und dann die Identitätseinfügung ausschalte.Ohne diesen Flush schien es, als würde die Identitätseinfügung ein- und ausgeschaltet und dann die Entität gespeichert.

Die Verwendung von Flush() gab mir mehr Kontrolle darüber, was vor sich ging.

Hier ist ein weiteres Beispiel:

Senden einer NServiceBus-Nachricht innerhalb von TransactionScope

Ich verstehe nicht ganz, warum das so ist, aber Flush() hat meinen Fehler verhindert.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top