У меня есть схема безопасности, в которой определенные объекты защищены ссылкой на SecureEntity. SecureEntity имеет набор RolePermissions, каждый из которых имеет флаг разрешения и приоритет. Идея состоит в том, чтобы сопоставить роли пользователя с RolePermissions на SecureEntity. Например, пользователю может быть разрешено разрешение с самым низким приоритетом, но ему может быть отказано с помощью разрешения с более высоким приоритетом, поэтому оно является наивысшим, что нас интересует. В этом примере корневой объект, который я запрашиваю, называется ProcessCategory.
(SecureRoleId соответствует роли пользователя; SecureRoleName - это просто строковое описание.)
Предположим, что у пользователя есть роли (1,2), а SecureEntity имеет RolePermissions:
SecureRoleId = 1, Priority = 0, Allow = true
SecureRoleId = 2, Priority = 1, Allow = false
В этом случае объект не будет выбран. Но если бы у пользователя была только роль 1, объект был бы выбран. Конечно, SecureEntity может содержать множество других ролей, которых у пользователя нет и которые не имеют отношения к делу.
Приведенный ниже код sql работает и делает следующее: «выберите объект, если разрешение роли с наивысшим приоритетом, которое также имеет пользователь, - Allow = true». Таким образом, он в основном фильтрует RolePermission для собственных ролей пользователей (предложение IN), сортирует по приоритету и берет наивысший из них, если это разрешение.
Вот 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 или критериев. Я потратил несколько часов, пытаясь заставить Linq работать, и потерпел неудачу с различными исключениями «недопустимая операция» при внутреннем присоединении к RolePermission. У меня нет большого опыта работы с ICriteria или MultiCriteria, и мне было бы интересно, может ли кто-нибудь мне помочь.
Обратите внимание, что сопоставление объектов Fluent простое:
<some-entity>.References(x => x.SecureEntity)
и
SecureEntity.HasMany(x => x.RolePermissions).Not.Inverse();