首页 > 解决方案 > 如何选择连接两个表的子行

问题描述

我有两张桌子:

1- 屏幕(ID、IsCheck、ParentID、IsActive)

2- RoleScreen (ID,RoleID,ScreenID)

现在我有一个 RoleID 的整数列表。我想选择列表 RoleIDs 中存在的所有屏幕以及 IsCheck 为 false 的所有子屏幕。RoleScreen 表中不存在子屏幕 ID。

我尝试了以下代码,但它没有返回 IsCheck = false 的子屏幕:

  this.context.Screens.Where(x => (x.IsActive == true) && 
                                  (
                                    (x.RoleScreens.Any(y => listUserRoleIDs.Any(z => z == y.RoleID))) ||
                                    (x.RoleScreens.Any(y => x.IsCheck== false && y.ScreenID == x.ParentID && listUserRoleIDs.Any(z => z == y.RoleID)))
                                  )).ToList();                  

请指导我我做错了什么。

标签: c#lambdaentity-framework-6

解决方案


假设您有以下型号

  public class Screen
  {
      public Guid ID { get; set; }
      public bool IsCheck { get; set; }
      public Guid ParentID { get; set; }
      public bool IsActive { get; set; }
      public Screen Parent { get; set; }
      public ICollection<Screen> Children { get; set; }
      public RoleScreen RoleScreen { get; set; }
  }

  public class RoleScreen
  {
      public Guid ID { get; set; }
      public Guid RoleID { get; set; }
      public Guid ScreenID { get; set; }
      public Screen Screen { get; set; }
  }

你想检索:

  • 属于给定角色 ID 列表的所有屏幕
  • 给定屏幕的所有子IsCheck屏幕false
  • 不属于RoleScreens表的所有子屏幕

简而言之,它检索在角色 ID 及其子屏幕列表中指定的任何屏幕。然而,这个问题最终可能会出现在列表中有其父级的子屏幕的子屏幕(递归问题)。但是,如果您只对直系子女感到满意,则此查询将满足您的需求:

  this.context.Screens.Where(x => (x.IsActive == true) && 
                                  (
                                    //Retrieve all Screen designated in RoleScreen
                                    (x.RoleScreens.Any(y => listUserRoleIDs.Any(z => z == y.RoleID))) ||
                                      //Retrieve all Child Screens
                                      ((x.Parent != null)
                                                         //Retrieve all Child Screens that don't have role assignment
                                                         && ((x.RoleScreen == null) || 
                                                         // Retrieve immediate children of the Screen designated in RoleScreen
                                                         // this part will need to be recursed somehow that is difficult if not utterly costly or impossible in classic linq
                                                         ((x.Parent.RoleScreens.Any(y => listUserRoleIDs.Any(z => z == y.RoleID)))
                                                           && (x.IsCheck == false))))
                                  )).ToList();

免责声明:我没有实际测试过查询。与谷物和大量盐一起服用。我希望有人能提出更好的查询。


推荐阅读