2012-12-19 11 views
12

Gibt es einen Grund, nicht dynamic-insert/dynamic-update für NHibernate zu verwenden? Der einzige Grund, den ich stelle, ist, dass es etwas zu sein scheint, das ich als Standard aktiviert haben sollte, nicht als etwas, das ich konfigurieren müsste.NHibernate dynamic-update Nachteile?

Ist bei der Verwendung dieser dynamischen Eigenschaften etwas zu beachten?

Antwort

23

Für einige Entitäten können Sie einen ungültigen Status durch dynamische Updates erstellen. Nehmen wir an, Sie haben eine Class mit einer Boolean Eigenschaft A und eine logisch abhängige Integer Eigenschaft B. Wenn die Eigenschaft ATrue ist, dann kann die Eigenschaft B nur eine negative Zahl sein. Wenn die Eigenschaft AFalse ist, kann die Eigenschaft B nur eine positive Zahl sein.

Nehmen wir an, dass zwei Benutzer innerhalb einer bestimmten Zeitspanne mit einer Instanz dieser Klasse interagieren. Um zu beginnen, Benutzer Alice und Bob materialisieren beide diese Klasse aus der Datenbank, mit den Anfangswerten von A = True und B = -50

Database Alice  Bob 
A: True A: True  A: True 
B: -50  B: -50  B: -50 
VALID  VALID  VALID 

Benutzer Alice ändert A-False und B-125, und verpflichtet sie zur Datenbank. Jetzt haben wir diese Situation:

Database Alice  Bob 
A: False A: False A: True 
B: 125  B: 125  B: -50 
VALID  VALID  VALID 

Benutzer Bob nicht A ändert, ändert aber B bis -75, dann begeht sie in die Datenbank. Wenn Dynamische Updates aktiviert sind, erkennt NHibernate, dass Bob nur B in -75 geändert hat, und gibt ein dynamisches Update aus, das nur den Wert B bearbeitet. Wenn Sie eine SQL-Validierung auf dem Server hatten, um zu verhindern, dass B negativ wird, es sei denn, A war wahr, dann erhalten Sie hier einen SQL-Fehler, aber Sie haben nicht Ihre gesamte Geschäftslogik auf Ihren SQL-Tabellen reproduziert. Hier sind die resultierenden Daten:

Beide Alice und Bob haben gültige Zustände, aber die Datenbank ist jetzt in einem ungültigen Zustand! Benutzer Charlie kommt und versucht, diesen Rekord zu materialisieren:

Database Alice  Bob  Charlie 
A: False A: False A: True A: False 
B: -75  B: 125  B: -75 B: -75 
INVALID VALID  VALID  INVALID 

Charlie würde wahrscheinlich einen Fehler bei der Überprüfung von Ihrer Anwendung erhalten, wenn NHibernate die B-Eigenschaft der neuen Instanz der Klasse zu setzen versucht.

Wenn Sie also logisch abhängige Eigenschaften haben, müssen Sie eine Strategie haben, um diese Situation zu vermeiden. Eine Möglichkeit besteht darin, einfach select-before-update für diese Entität zu aktivieren. Dies kann zu einigen zusätzlichen Datenbankaufrufen und einer etwas langsameren Leistung führen. Eine andere Möglichkeit ist die Versionierung in NHibernate, was bedeutet, dass, wenn Bob versucht, seinen Datensatz zu speichern, die Einfügeabfrage von NHibernate keine Schreibvorgänge auslöst und eine veraltete Datenausnahme auslöst (die ordnungsgemäß behandelt werden kann). Sie könnten auch die logischen Anforderungen Ihrer Klasse in der Datenbank kodifizieren, aber Sie müssen dann vorsichtig sein, um sicherzustellen, dass die Datenbank und das Programm beide die gleichen kodifizierten Anforderungen wie die Zeit hat, und Sie haben mehrere Orte zu Änderungen vornehmen, wenn sich die Anforderungen ändern, was nicht immer ein lohnender Aufwand ist.

Kurz gesagt, in vielen Fällen muss ein Entwickler die Details von dynamischen Updates sorgfältig behandeln, weshalb er nicht standardmäßig aktiviert ist.Denken Sie beim Einschalten daran, ob durch eine teilweise Aktualisierung Ihrer Entität Probleme verursacht werden könnten, und wenn dies der Fall ist, wenden Sie eine der empfohlenen Schutzstrategien an, die Sie vor diesem Problem schützen möchten.

+0

Sehr informativ. Ich war mir nicht einmal bewusst, vor dem Update zu wählen. Ich werde das im Hinterkopf behalten. – Sam

+2

In diesem Beispiel erlaubte die Anwendung dem Benutzer, Änderungen festzuschreiben, während sich die Entität in einem ungültigen Zustand befand. Die Klasse sollte den Zugriff auf diese Eigenschaften kapseln, sodass die Geschäftsregel erzwungen wird, und/oder die Entität muss validiert werden, bevor die Transaktion festgeschrieben wird. Ich sehe nicht, dass dies etwas mit dynamischem Update zu tun hat. –

+0

Sie vermissen die Lektion hier: Bobs Kopie der Entität war nicht in einem ungültigen Zustand. Die Entität wurde nur ungültig, wenn die dynamische Aktualisierung den Wert von Eigenschaft B änderte, ohne die Information zu erhalten, dass der beibehaltene Wert von Eigenschaft A diesen Wert ungültig machen würde. –

5

Dynamische Einfügung und Aktualisierung haben leichte Leistungskosten, da NHibernate die SQL jedes Mal erstellen muss, anstatt sie zwischenzuspeichern. Ich weiß nicht, ob auf der Datenbankseite Kosten anfallen. Dynamische Einfügung und Aktualisierung sind sehr praktisch für die Fehlersuche und Profilerstellung. Wenn ich in der Lage wäre, einen bedeutenden Leistungseinbruch zu messen, würde ich ihn in der Entwicklung und in der Produktion einschalten.

Möglicherweise treten Probleme mit Listenern und Interzeptoren auf, siehe this question.

Ich habe es in meinen NHibernate-Anwendungen ohne Probleme eingeschaltet. Meine Antwort ist nein, es gibt keinen guten Grund, es nicht zu benutzen.

+0

Neugierig auf Ihre Kommentare zum Caching. Wenn ich mir das mit log4net erzeugte SQL ansehe, scheint es immer noch parametrisierte Abfragen zu verwenden. Werden diese nicht irgendwo auf der Linie zwischengespeichert? Lassen auch dynamische Abfragen keine Leistungseinbußen durch Aktualisieren von Feldern, die sich nicht geändert haben? Oder sind diese Kosten vernachlässigbar? Danke für die Rückmeldung. – Sam

+2

NHibernate kann ein statisches Abfrageformat zwischenspeichern, sodass beim Erstellen einer Abfrage nur die leeren Felder ausgefüllt werden. Bei dynamischen Abfragen muss die Abfrage jedes Mal neu erstellt werden. Der Performance-Treffer bei der Aktualisierung aller Felder, falls vorhanden, ist datenbankabhängig. Es gibt eine Reihe von Faktoren, aber aufgrund meiner Meinung und Erfahrung empfehle ich die Verwendung von dynamischem Einfügen und Aktualisieren. –