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
sauve AuditLog dans la même transaction que l'entité principale? – dariol
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. –