簡體   English   中英

流利的NHibernate:如何為中間表設置默認值

[英]Fluent NHibernate: How to set default values for intermediate table

我正在使用NHibernate和Fluent NHibernate進行映射的.NET MVC應用程序。 我有用戶表和角色表/類,它們是通過中間表UserRole映射的。 所以我的映射工作正常; 我在用戶映射中有:

HasManyToMany(user => user.Roles).Cascade.SaveUpdate()

因此,當我使用一個新角色來保存用戶時,它將嘗試插入新的UserRole行。 大。

唯一的問題是,我在UserRole表上具有不可為null的審核列(例如“ UpdatedBy”和“ UpdatedDate”)。 我嘗試在UserRole構造函數中設置它們,但是顯然它從未被調用,因為流利的Nhibernate只是直接進入數據庫並嘗試插入沒有審計列的新UserRoles。

所以我只是想知道是否有任何干凈的方法可以在Fluent Nhibernate中為這些列設置默認值。 我可以關閉層疊,並在保存用戶時手動進行所有操作,但是我想知道是否有更干凈直接的方法來執行此操作。

使用完整的審核系統(例如Envers) ,或為自定義審核用例添加一些攔截器。

但是,向關聯表添加其他屬性會使它很難作為僅通過多對多關系映射的純關聯表來處理。

您可能會更容易將其映射為中間實體(然后最好向其添加代理鍵),並通過多對一關系鏈接到您的User和Role實體。

攔截器將對任何更新或插入做出反應,並相應地設置審核屬性。 對於實體和映射的審計屬性,這很容易。 對於您的情況,您必須修補發出的SQL。

這是我使用的一種,用於設置創建者(映射到某些用戶實體上並且不能為空),創建日期(映射到並且不能為空),更新程序,更新日期(映射和可以為空)。 (改編自此NH參考示例此博客文章 。)

對於您的情況,您可能需要將覆蓋添加到SqlString OnPrepareStatement(SqlString sql)可能與void OnCollectionUpdate(object collection, object key)void OnCollectionRecreate(object collection, object key)

// Interceptor setting up audit properties.
[Serializable]
public class AuditInterceptor : NHibernate.EmptyInterceptor
{
    public YourAppUser AppUser { get; set; }

    public override bool OnFlushDirty(object entity,
        object id,
        object[] currentState,
        object[] previousState,
        string[] propertyNames,
        NHibernate.Type.IType[] types)
    {
        var modified = false;
        for (int i = 0; i < propertyNames.Length; i++)
        {
            switch (propertyNames[i])
            {
                case "UpdateDate":
                    currentState[i] = DateTimeOffset.Now;
                    modified = true;
                    break;
                case "Updater":
                    currentState[i] = AppUser;
                    modified = true;
                    break;
            }
        }
        return modified;
    }

    public override bool OnSave(object entity,
        object id,
        object[] state,
        string[] propertyNames,
        NHibernate.Type.IType[] types)
    {
        var modified = false;
        for (int i = 0; i < propertyNames.Length; i++)
        {
            switch (propertyNames[i])
            {
                case "CreationDate":
                    state[i] = DateTimeOffset.Now;
                    modified = true;
                    break;
                case "Creator":
                    state[i] = AppUser;
                    modified = true;
                    break;
            }
        }
        return modified;
    }
}

在打開會話時注入攔截器實例:

yourNHibernateSessionFactory.OpenSession(yourInterceptorInstance);

而且,在業務邏輯處理其工作之前,應設置當前用戶的攔截器。 就我而言,我在動作過濾器OnActionExecuting方法中執行此操作,使用依賴項解析程序獲取我的攔截器,該攔截器具有每個http請求的生存期管理器。

此攔截器假定任何名為CreatorUpdater的屬性AppUser屬性,而任何名為CreateDateUpdateDate屬性均為datetimeoffset 舉例來說,您可能想通過檢查entity是否實現了一些自定義接口來保證這種假設(就像參考示例所做的那樣,進行諸如if (!(entity is IYourAuditableInterface)) return false;類的檢查)。 或者,您也可以檢查types參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM