2009-08-26 103 views
1

更新之前比較實體,我需要登錄到數據庫中的每個用戶更新任何記錄,需要存儲哪些改變任何記錄的新老值。本次審計是實現爲NHibernate的攔截,所以我有方法:在NHibernate的(審計實施)

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

,我需要用實體的以前的狀態,比較目前的狀態,我不知道如何做到這一點(它應該是通用的解決方案,我可以適用於很多類型)

回答

0

我不確定這正是你問的問題,b/c似乎答案只是循環currentState數組,並與previousState數組相比較,以獲得相同的索引值。要更改的屬性名稱是在同一索引處的propertyName值

儘管如果您在會話之外修改實體(Nhibernate稱之爲「分離」模型),我會提醒您的是,我不認爲先前的狀態已填充(或者導致重新讀取數據的代價高昂)。

我的建議是使用你的數據庫表的觸發器爲您的審計日誌記錄。這是很容易恕我直言做這樣的,當你不通過NHib

乾杯更新甚至工程!

3

我剛纔問了一個類似的問題。 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

編輯 - 更新應答與實施
看它再次我需要重構它,因爲它沒有很多氣味,但當時我只是需要一些工作,而這是我想出來的。

這是我已經使用

<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類NHibernate的映射。

的IInterceptor的Implemetation像這樣(在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

是相同的事務中主要實體保存審計日誌? – dariol 2009-09-11 17:36:23

+0

對我來說,它應該是同一事務的一部分,這就是爲什麼我使用UnitOfWork.Start(UnitOfWorkNestingOptions。CreateNewOrNestUnitOfWork),以便它加入當前的UOW。我知道我在這個領域遇到問題,當我試圖讓它工作。使用CreateNewOrNestUnitOfWork選項作爲UOW的一部分產生了不同。 – 2009-09-14 23:09:05