不久前我问了一个类似的问题。
Audit Logging Strategies 也以不同的方式看待这个问题
how-do-i-implement-changetime-and-changeuser-columns-using-nhibernate
我最终将 IInterceptor 实现为一个类和一个通用审计日志 poco 类,其中包含实体类型、实体 ID、属性名称、当前状态、先前状态、更改类型(插入、更新、删除)和更改发生的日期时间。
然后我创建了一个空接口 IAuditable,以便可以识别我想要审计的每个类。
在 OnFlushDirty、OnDelete 和另一个我现在想不到的事件中,为每个已更改的属性添加了新的审计日志类。
当我回到家并可以访问我当前使用的代码时,我会更新这个问题。
也看
Frederik Gheysels' DevLog - NHibernate IInterceptor: an AuditInterceptor
编辑 - 通过实施更新答案
再看一遍我需要重构它,因为它确实很臭,但当时我只是需要一些东西来工作,这就是我想出的。
这是我用过的nhibernate映射
<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>
该类是实现这些属性中的每一个的通用 poco 类。
IInterceptor 的实现如下所示(在 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