这一点对我来说有点难以用书面解释,我感谢你们中的任何人花时间阅读这个冗长的问题。我不愿意使用LINQ查询来解决这个问题,只是做某种类型的循环或递归,如果效果更好的话。
我正在开发一个在某种程度上基于NETSqlAzMan的权限/授权系统。
这些是主要的概念:
这是一个更具体的例子,它是如何工作的。
保修品:
- Administrators
- Tom
- Mike
- Editors
- John
- Lisa
- Documents
- Document1
- Document2 权限:
- Edit\_Title
- Edit\_Body
- Change\_BGColor
上述数据存储在两个表中,安全表和权限表包含两个中间表: GroupMembership (安全层次结构)和PermissionRelationship (权限层次结构)。
还有一个名为“授权”的表,它包含由一个安全为"AuthorizedID“、一个安全为"SecurableID”、一个权限为"PermissionID“和一个Enum组成的授权,可以继承(0)、允许(1)或拒绝(2)。
我为所有表设置了LINQ2SQL实体,还设置了一个函数,该函数返回给定安全的所有祖先和返回所有给定权限的祖先。
我很难确定一个查询,该查询正确地检查每个权限的所有3个层次结构,以确定为给定的authorizedID和SecurableID设置的有效权限和最近级别的授权。
例如:如果授予管理员对"Edit_Document“权限的”允许“,那么对给定的”AuthorizedID“的”管理员“和”文档“的SecurableiD的查询应该返回:
另外,如果在"Document1“上添加了"Mike”和"Change_BGColor“的授权(拒绝重写链中的任何允许),那么查询"Mike”的AuthorizedID和"Document1“的SecurableID的结果将返回:
这就是我到目前为止处理AuthorizedID和SecurableID层次结构的方法,但是没有正确地考虑权限层次结构。我不确定如何将权限层次结构考虑在内,以便如果权限的一个祖先被设置为拒绝,那么子权限也会显示拒绝,结果包括设置拒绝的AuthorizedID和SecurableID。
public List<LocalPermission> GetSecurablesLocalPermissions(Guid authorizedID, Guid securableID)
{
var localAuthorization = (from eff in
(from p in dc.Permissions
let a = (from sa in dc.AllSecurablesAuthorizations(authorizedID)
where sa.PermissionID == p.PermissionID
group sa by sa.PermissionID into g
select g.OrderBy(x => x.Lvl).OrderByDescending(x => x.AuthorizationBits).First()).FirstOrDefault()
select new
{
PermissionID = p.PermissionID,
PermissionName = p.PermissionName,
AuthorizationBits = a.AuthorizationBits ?? 0,
SecurableID = a.SecurableID ?? Guid.Empty,
SecurableName = a.SecurableName,
AuthorizedName = a.AuthorizedName,
AuthorizedID = a.AuthorizedID ?? Guid.Empty
})
join l in
(from p in dc.Permissions
join la in dc.Authorizations
on p.PermissionID equals la.PermissionID into laJoin
from localJoin in laJoin.Where(x => (x.SecurableID == securableID /*|| localJoin.SecurableID == Guid.Empty*/) && (x.AuthorizedID == authorizedID /*|| localJoin.AuthorizedID == Guid.Empty*/)).DefaultIfEmpty()
select new
{
PermissionID = p.PermissionID,
PermissionName = p.PermissionName,
AuthorizationBits = localJoin == null ? 0 : localJoin.AuthorizationBits,
SecurableID = localJoin == null ? Guid.Empty : localJoin.SecurableID,
SecurableName = localJoin == null ? null : localJoin.SecurableName,
AuthorizedName = localJoin == null ? null : localJoin.AuthorizedName,
AuthorizedID = localJoin == null ? Guid.Empty : localJoin.AuthorizedID
}) on eff.PermissionID equals l.PermissionID
select new LocalPermission
{
PermissionID = l.PermissionID,
PermissionName = l.PermissionName,
AuthorizationBits = l.AuthorizationBits,
SecurableID = securableID,
SecurableName = (from s in dc.Securables
where s.SecurableID == securableID
select s).SingleOrDefault().SecurableName,
AuthorizedID = authorizedID,
AuthorizedName = (from s in dc.Securables
where s.SecurableID == authorizedID
select s).SingleOrDefault().SecurableName,
EffectiveAuthorizationBits = eff.AuthorizationBits == 0 ? l.AuthorizationBits : eff.AuthorizationBits
}).ToList<LocalPermission>();
return localAuthorization;
}发布于 2011-02-08 21:40:09
这太恶心了。
回答:“因此,如果权限的一个祖先被设置为拒绝,那么子权限也会显示拒绝”,这意味着您需要递归。数据库中的父/子关系通常意味着递归。linq不支持递归,但本机sql支持递归(公共表表达式)。
我的策略是将所有权限都拉到一个列表中,然后编写普通的过程递归代码来回答您的查询(我没有完全理解)。在这种情况下,我推荐TDD。希望这能让你走上正轨。
https://stackoverflow.com/questions/4925437
复制相似问题