簡體   English   中英

將此SQL查詢轉換為NHibernate Linq或Criteria?

[英]Translate this Sql query into NHibernate Linq or Criteria?

我有一個安全模式,其中某些實體通過具有SecureEntity引用來保護。 SecureEntity具有RolePermissions的集合,每個角色都有一個Allow標志和一個Priority。 這個想法是將用戶的角色與SecureEntity上的RolePermissions進行匹配。 例如,一個用戶可能會被其最低優先級權限所允許,但被較高優先級的權限所拒絕,因此它是我們感興趣的最高權限。在此示例中,我要查詢的根實體稱為ProcessCategory。

架構圖

(SecureRoleId是用戶角色的匹配項; SecureRoleName只是字符串描述。)

假設用戶具有角色(1,2),並且SecureEntity具有RolePermissions:

SecureRoleId = 1, Priority = 0, Allow = true
SecureRoleId = 2, Priority = 1, Allow = false

在這種情況下,將不會選擇實體。 但是,如果用戶僅具有角色1,則將選擇實體。 當然,SecureEntity可能包含用戶沒有的,不相關的許多其他角色。

下面的sql代碼可以運行並執行以下操作:“如果用戶還具有的最高優先級角色權限為Allow = true,則選擇實體”。 因此,它基本上是根據用戶自己的角色(IN子句)過濾RolePermission,按優先級排序,如果允許則采用最高的權限。

這是Sql:

select pc.* from ProcessCategory pc
join SecureEntity se 
    join RolePermission rp on se.SecureEntityId = rp.SecureEntityId 
on pc.SecureEntityId = se.SecureEntityId
where rp.RolePermissionId = (select top 1 RolePermissionId 
                from RolePermission
                where Allow = 1
                and SecureEntityId = se.SecureEntityId
                and SecureRoleId in(0,1)
                order by Priority desc)

可能有另一種方式編寫上面的Sql,但是它滿足了我的需要。 理想情況下,我想使用NHibernate Linq或Criteria實現。 我花了幾個小時試圖使Linq正常工作,但在與RolePermission的內部聯接上出現各種“無效操作”異常而失敗。 我在ICriteria或MultiCriteria方面沒有太多經驗,如果有人可以幫助我,我會很感興趣。

請注意,對象的Fluent映射非常簡單:

 <some-entity>.References(x => x.SecureEntity) 

 SecureEntity.HasMany(x => x.RolePermissions).Not.Inverse();

好的。 我無法使用本機 NH Linq來實現此目的,盡管這並不意味着不可能。 但是我仔細檢查了Linq的所有NH單元測試,找不到任何等效的東西。

為了使其正常工作,我創建了一個名為UserHasPermission的數據庫函數,該函數可以執行以下操作:

on pc.SecureEntityId = se.SecureEntityId
where rp.RolePermissionId = (select top 1 RolePermissionId 
            from RolePermission
            where Allow = 1
            and SecureEntityId = se.SecureEntityId
            and SecureRoleId in(0,1)
            order by Priority desc)

這適用於任何類型的安全實體。 然后,我按照此頁面中的說明將該函數映射為NH Linq函數: http : //wordpress.primordialcode.com/index.php/2010/10/01/nhibernate-customize-linq-provider-user-defined- sql-functions /

如果遵循這些說明,則必須在C#中創建一個普通的LinqToObjects擴展,其擴展名與數據庫的簽名相同。 然后,您可以執行NH Linq查詢,例如:

return base.Query<T>().Where(c => ((ISecureEntity)c)
            .SecureEntity.Id
            .UserHasPermissions(user.SecureRoleIdsCsv) == 1);

我發現的唯一問題是我原來的Sql函數返回了一點,並將其映射到NH布爾類型。 但是,這產生了一個非常奇怪的sql語句,其中包含幾個在SQL Server中炸毀的“ Where” True” =“ True””子句。 所以我將結果更改為整數,一切正常。 有點違反直覺,但是...

通過這種方式,我可以對所有查詢透明地使用Linq進行操作,而不會影響現有代碼,因為它會自動在每個查詢之前進行安全檢查。

請注意,我查看了Rhino Security源代碼,它使用了多個標准,對於我有限的NH知識來說,這對於我來說太復雜了。 如果我使用CreateCriteria完成此操作,是否可以將其與Linq結合使用?

  • 上面鏈接中的說明並不清楚,當您創建自己的方言來注冊Sql函數時,必須確保在NH配置文件(或代碼)中引用它,否則您將獲得某種“未知類型”異常。

暫無
暫無

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

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