[英]Translate LINQ to SQL query to NHibernate (child collection filter)
[英]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結合使用?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.