2009-08-26 8 views
1

Je dois me connecter à la base de données à chaque mise à jour d'utilisateur sur n'importe quel enregistrement et stocker l'ancienne et la nouvelle valeur de tout enregistrement modifié. Cet audit est mis en œuvre comme intercepteur dans NHibernate si j'ai méthode:comparer les entités avant la mise à jour dans Nhibernate (implémentation d'audit)

public override bool OnFlushDirty(
      object entity, 
      object id, 
      object[] currentState, 
      object[] previousState, 
      string[] propertyNames, 
      IType[] types) 

et je dois comparer l'état actuel avec l'état précédent de l'entité et je ne sais pas comment faire (il devrait être solution générique qui i peut s'appliquer à plusieurs types)

Répondre

0

Je ne suis pas sûr que ce soit exactement ce que vous demandez, b/c il semble que la réponse est juste une boucle dans le tableau currentState et comparer au tableau previousState pour la même valeur d'index. Le nom de propriété en cours de modification est la valeur propertyName au même index

Je vous préviens que si vous modifiez vos entités en dehors d'une session (Nhibernate l'appelle un modèle "détaché"), je ne pense pas que l'état précédent soit rempli (ou cela entraîne une relecture coûteuse des données pour le faire).

Ma recommandation serait d'utiliser des triggers sur vos tables de base de données pour votre journalisation d'audit. Il est beaucoup plus facile à mon humble avis de le faire de cette façon et fonctionne même lorsque vous ne mettez pas à jour par NHib

Cheers!

3

J'ai posé une question similaire en arrière. Audit Logging Strategies Regardez aussi cette question d'une façon différente how-do-i-implement-changetime-and-changeuser-columns-using-nhibernate

Ce que je fini par mettre en œuvre le IInterceptor comme une classe et une classe générique auditlog poco qui contenait le type d'entité, l'entité Id, nom de la propriété, l'état actuel, précédent état, le type de changement (Insert, Update, Delete) et le datetime le changement est arrivé.

Puis j'ai créé une interface vide IAuditable afin que chaque classe que je voulais auditer puisse être identifiée.

Dans le OnFlushDirty, OnDelete et un autre événement auquel je ne peux pas penser maintenant, ajouté de nouvelles classes auditlog pour chaque propriété qui avait changé.

Je vais mettre à jour cette question quand je rentre à la maison et que j'ai accès au code que j'utilise actuellement.

Regardez aussi Frederik Gheysels' DevLog - NHibernate IInterceptor: an AuditInterceptor

Modifier - Mise à jour de réponse à la mise en œuvre
regardant à nouveau je dois factoriser comme il ne sent beaucoup, mais au moment où je avais juste besoin quelque chose à travailler, et cela est ce que je suis venu avec.

Ceci est la cartographie NHibernate que je l'ai utilisé

<class name="AuditLog" table="AuditLog" lazy="true" > 
     <id name="_persistenceId" column="Id" type="Guid" access="field" unsaved-value="00000000-0000-0000-0000-000000000000" > 
      <generator class="guid.comb" /> 
     </id> 
     <version name="_persistenceVersion" column="RowVersion" access="field" type="int" unsaved-value="0"/> 
     <property name="CreatedDate" column="CreatedDate" type="DateTime" /> 
     <property name="UpdatedBy" column="UpdatedBy" type="string" length="100" /> 
     <property name="EntityID" column="EntityID" type="guid" not-null="true" /> 
     <property name="EntityName" column="EntityName" type="String" length="100" not-null="true" /> 
     <property name="PropertyName" column="PropertyName" type="String" length="100" not-null="true" /> 
     <property name="ActionType" column="ActionType" type="Char" length="1" not-null="true" /> 
     <property name="OldValue" column="OldValue" type="String" length="1000" not-null="false" /> 
     <property name="NewValue" column="NewValue" type="String" length="1000" not-null="false" /> 
    </class> 

La classe est une classe poco générale qui implémente chacune de ces propriétés.

Le IInterceptor de l'Implémentation ressemble à ceci (en VB.Net)

Imports Rhino.Commons 
Public Class AuditInterceptor 
Inherits NHibernate.EmptyInterceptor 
Private _auditLogRepository As IAuditLogRepository 
Public Sub New(ByVal [AuditLogRepository] As IAuditLogRepository) 
    _auditLogRepository = [AuditLogRepository] 
End Sub 
Public Overrides Function OnFlushDirty(ByVal entity As Object, ByVal id As Object, ByVal currentState() As Object, ByVal previousState() As Object, ByVal propertyNames() As String, ByVal types() As NHibernate.Type.IType) As Boolean 
'Called on an Update 

    If TypeOf entity Is IAuditable Then 
     Using uow = UnitOfWork.Start(UnitOfWorkNestingOptions.CreateNewOrNestUnitOfWork) 
      If TypeOf entity Is [yourObject] Then 
       aLog = New AuditLog(Now, My.User.Name) 
       With aLog 
        .EntityID = id 
        .EntityName = "[yourObject]" 
        .PropertyName = "[yourProperty]" 
        .ActionType = "U" 
        .OldValue = GetPropertyValue("[yourProperty]", previousState, propertyNames) 
        .NewValue = GetPropertyValue("[yourProperty]", currentState, propertyNames) 
       End With 
       _auditLogRepository.Save(aLog)  
      End if 
      uow.Flush() 
     End Using 
    End If 

    Return MyBase.OnFlushDirty(entity, id, state, propertyNames, types) 
End Function 
Public Overrides Function OnSave(ByVal entity As Object, ByVal id As Object, ByVal state() As Object, ByVal propertyNames() As String, ByVal types() As NHibernate.Type.IType) As Boolean 
'Called on an Insert 

    If TypeOf entity Is IAuditable Then 
     'create a new audit log class here 
    end if 
    Return MyBase.OnSave(entity, id, state, propertyNames, types) 
End Function 
+0

sauve AuditLog dans la même transaction que l'entité principale? – dariol

+0

Pour moi, cela devrait faire partie de la même transaction, c'est pourquoi j'ai utilisé UnitOfWork.Start (UnitOfWorkNestingOptions.CreateNewOrNestUnitOfWork) afin qu'il rejoigne l'UOW actuel. Je sais que j'ai eu des problèmes dans ce domaine quand j'essayais de le faire fonctionner. L'utilisation de l'option CreateNewOrNestUnitOfWork dans le cadre de l'UOW a fait la différence. –

Questions connexes