2009-03-09 19 views
9

estoy revisar y volver a implementar el código que me hizo pido this question acerca de la auditoría de datos en NHibernate. Sin embargo esta vez, quiero ir con Sean Carpenter 's suggestion e implementar el ISaveOrUpdateEventListener (nuevo en NHibernate 2.x)datos de auditoría en NHibernate usando eventos

Quiero añadir una fila en una base de datos para cada cambio de cada propiedad con el valor antiguo y el nuevo por lo que más adelante en la interfaz de usuario que puedo decir cosas como "usuario Bob cambió la propiedad de Wibble de a a B el 9 de marzo de 2009 a las 21:04"

¿Cuál es la mejor manera de comparar el estado del objeto de averiguar qué de las propiedades del objeto han cambiado?

que pueda obtener el estado de carga del objeto por el siguiente texto:

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

Y supongo que podría utilizar la reflexión para averiguar qué propiedades han cambiado, pero yo he estado cavando alrededor y no doesn' Parece ser un conjunto de propiedades que se combinan para comparar. Hubiera pensado que habría un método GetChangedProperties() o algo así.

siempre podía obtener el objeto de edad, de la base de datos tal como es y compararlo, pero eso es otra base de datos de golpear y parecería mano dura en este escenario.

Cuál es la mejor dirección a seguir con esto?

P.S. En caso de que haga alguna diferencia, este es un proyecto de arquitectura ASP.NET-MVC/S # arp.

Respuesta

6

no sabría cómo lograr lo que quiere con la interfaz ISaveOrUpdateListener - sin embargo, puede aprovechar el hecho de que IPreUpdateEventListener y IPreInsertEventListener interfaces de ambos proporcionan lo que necesita ... por ejemplo, haga algo como esto:

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' 
     // (...) 
    } 
} 

y haga lo mismo para pre insert.

+0

Esto funcionó para mí. Gracias mookid. –

+0

Gracias por "y obtener el nombre de la propiedad modificada de 'nombres'". Estuve en la red durante 15 minutos buscando una manera confiable de unir el objeto a los valores. – SamuelKDavis

0

podría implementar un patrón Memento para serializar el estado de la carga inicial, a través de ILoadEventListener. Obviamente, no desea almacenar colecciones/relaciones o duplicaría el gráfico completo del objeto. Luego puede sacar esto y comparar en su ISaveOrUpdateEventListener.

11

También es posible usar el método FindDirty en el persister para que NHibernate hacer las comparaciones para usted:

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

todo tipo de impresionante! –

Cuestiones relacionadas