从另一个列表和属性中获取列表结果

时间:2014-01-30 14:42:58

标签: c# linq

我有以下3个(简化的)模型类,每个类都包含另一个的集合:

Group.CollectionOfPermissions
Group.CollectionOfUsers
User.CollectionOfGroups
User.CollectionOfPermissions
Permission.CollectionOfGroups
Permission.CollectionOfUsers

我有一个基于单个User.ID的View,我希望能够为所述用户返回有效权限。

有效权限基于:

  1. 各个用户的权限,只是User.CollectionOfPermissions属性。
  2. 用户所属组的派生权限。也就是说,对于用户所属的每个组,我也需要获取这些权限。
  3. 数字1显然与引用集合属性一样简单。 数字2是我在LINQ选择上遇到的麻烦。

    我可以按照以下方式编写存储过程:

    SELECT * FROM PERMISSIONS P WHERE P.ID IN
    (SELECT PERMISSION_ID FROM PERMISSION_GROUP_REF PGR WHERE PGR.GROUP_ID IN
    (SELECT ID FROM GROUPS G WHERE G.ID IN 
    (SELECT GROUP_ID FROM GROUP_USER_REF GUR WHERE GUR.USER_ID IN
    (SELECT ID FROM USERS U WHERE U.ID = @USERID))))
    

    但我宁愿保持这与项目的其余部分保持一致并继续使用LINQ,特别是因为我想避免直接查询代码中的引用表(假设集合已经作为类属性存在)。我将如何处理这种LINQ查询?

    编辑:这是使用实体框架6和Razor 3

2 个答案:

答案 0 :(得分:2)

Users.Where(u => u.UserId == userId)
     .SelectMany(u => u.CollectionOfPermissions)
     .Select (cp=>cp.Permission) // you might need to do this too
     .Union(Users.Where(u => u.UserId == userId)
                 .SelectMany(u => u.CollectionOfGroups)
                 .SelectMany(cg => cg.Permission))

可能是这样的。

编辑:作为参考,这会产生以下SQL(我的测试装备中的列名略有不同): -

SELECT 
[Distinct1].[C1] AS [C1]
FROM ( SELECT DISTINCT 
    [UnionAll1].[Permission_Id] AS [C1]
    FROM  (SELECT 
        [Extent1].[Permission_Id] AS [Permission_Id]
        FROM [dbo].[PermissionPersons] AS [Extent1]
        WHERE 1 = [Extent1].[Person_Id]
    UNION ALL
        SELECT 
        [Extent3].[Permission_Id] AS [Permission_Id]
        FROM  [dbo].[PersonGroups] AS [Extent2]
        INNER JOIN [dbo].[PermissionGroups] AS [Extent3] ON [Extent2].[Group_Id] = [Extent3].[Group_Id]
        WHERE 1 = [Extent2].[Person_Id]) AS [UnionAll1]
)  AS [Distinct1] 

另一方面,为什么不一起查询Permission实体?

context.Permissions.Where(p=>
                           p.Groups.Any(gr=>gr.Users.Any(u=>u.UserId == userId)) 
                           || p.Users.Any(u=>u.UserId == userId))
                   .Distinct()

答案 1 :(得分:0)

您发布的SQL转换为:

PERMISSIONS.Where(p =>
  PERMISSION_GROUP_REF.Where(pg =>
    GROUPS.Where(g =>
      GROUP_USER_REF.Where(gu => gu.USER_ID == USERID)
                    .Any(gu => gu.GROUP_ID == g.ID))
          .Any(g => g.ID == pg.GROUP_ID))
        .Any(pg => pg.PERMISSION_ID == p.ID))

也许你可以稍微简化它,但这应该有效。