2009-03-09 3 views
9

Ich besuche den Code erneut, der mich veranlasste, this question über Datenüberwachung in NHibernate zu stellen. Aber dieses Mal möchte ich mit Sean Carpenter geht ‚s suggestion und Umsetzung der ISaveOrUpdateEventListener (neu in NHibernate 2.x)Datenüberwachung in NHibernate mithilfe von Ereignissen

ich mit dem alten Wert jeder Eigenschaft eine Zeile in einer Datenbank für jede Änderung hinzufügen möchten, und die neue ich kann so später im UI sagen Sachen wie „User Bob Wibble das Eigentum von A nach B am 9. März 2009 um 21:04 Uhr geändert“

Was ist der beste Weg, den Objektstatus vergleichen um herauszufinden, welche von Die Eigenschaften des Objekts haben sich geändert?

Sie können den geladenen Zustand des Objekts erhalten, indem die folgenden:

public void OnSaveOrUpdate(SaveOrUpdateEvent saveOrUpdateEvent) 
    { 
     object[] foo = saveOrUpdateEvent.Entry.LoadedState; 
    } 

Und ich nehme an, ich Reflektion verwenden könnte herauszufinden, welche Eigenschaften haben sich geändert, aber ich habe um gegraben, und es doesn‘ Es scheint ein passender Satz von zu vergleichenden Eigenschaften zu sein. Ich hätte gedacht, dass es eine GetChangedProperties() -Methode oder etwas geben würde.

Ich konnte immer das alte Objekt aus der Datenbank holen und vergleichen, aber das ist noch ein Datenbanktreffer und würde in diesem Szenario schwerfällig erscheinen.

Was ist die beste Richtung damit?

P.S. Falls es einen Unterschied macht, ist dies ein ASP.NET-MVC/S # arp Architecture-Projekt.

Antwort

6

Ich würde nicht wissen, wie Sie erreichen, was Sie wollen mit der ISaveOrUpdateListener Schnittstelle - Sie könnten jedoch die Tatsache nutzen, dass IPreUpdateEventListener und IPreInsertEventListener Schnittstellen bieten beide, was Sie brauchen ... z. Tun Sie etwas wie das:

public bool OnPreUpdate(PreUpdateEvent evt) 
{ 
    string[] names = evt.Persister.PropertyNames; 
    for(int index = 0; index < names.Length; index++) 
    { 
     // compare evt.State[index] to evt.OldState[index] and get 
     // the name of the changed property from 'names' 
     // (...) 
    } 
} 

und das gleiche für Pre-Einfügung tun.

+0

Das ist für mich gearbeitet. Danke Mookid. –

+0

Danke für die "und erhalten Sie den Namen der geänderten Eigenschaft von 'Namen'". Ich war 15 Minuten im Netz und suchte nach einer zuverlässigen Methode, um das Objekt an die Werte anzupassen. – SamuelKDavis

0

Sie könnten ein Memento-Muster implementieren, um den Status vom anfänglichen Laden zu initialisieren, über ILoadEventListener. Offensichtlich möchten Sie keine Sammlungen/Beziehungen speichern oder das gesamte Objektdiagramm duplizieren. Sie können dies dann herausziehen und in Ihrem ISaveOrUpdateEventListener vergleichen.

11

Sie könnten auch die FindDirty Methode auf dem Persister verwenden NHibernate tun, um die Vergleiche für Sie zu lassen:

var dirtyFieldIndexes = @event.Persister.FindDirty(@event.State, @event.OldState, @event.Entity, @event.Session); 

foreach (var dirtyFieldIndex in dirtyFieldIndexes) 
{ 
    var oldValue = @event.OldState[dirtyFieldIndex]; 
    var newValue = @event.State[dirtyFieldIndex]; 

    // Log values to new "AuditLog" object and save appropriately. 
} 
+0

alle Arten von genial! –