У меня есть схема безопасности, где определенные объекты защищены с помощью ссылки SecureEntity. SecureEntity имеет коллекцию RolePermissions, каждый из которых имеет флаг Allow и приоритет. Идея состоит в том, чтобы сопоставить роли пользователя с 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 или Criteria. Я потратил несколько часов, пытаясь заставить работать Linq, и потерпел неудачу с различными исключениями «недопустимая операция» во внутреннем соединении с RolePermission. У меня нет большого опыта работы с ICriteria или MultiCriteria, и мне было бы интересно, если кто-нибудь может мне помочь.
Обратите внимание, что отображение Fluent для объектов является простым:
<some-entity>.References(x => x.SecureEntity)
и
SecureEntity.HasMany(x => x.RolePermissions).Not.Inverse();