Как выбрать дочерние строки, соединяющие две таблицы - PullRequest
0 голосов
/ 22 мая 2018

У меня есть две таблицы:

1- Экран (ID, IsCheck, ParentID, IsActive)

2- RoleScreen (ID, RoleID, ScreenID)

Теперь яиметь целочисленный список RoleID.Я хочу выбрать все экраны, которые существуют в списке RoleID, а также все дочерние экраны, где IsCheck имеет значение false.Дочерние идентификаторы экрана не существуют в таблице RoleScreen.

Я попробовал следующий код, но он не возвращает дочерний экран с 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();                  

Пожалуйста, сообщите мне, что я делаю неправильно.

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

Если у вас есть следующие модели

  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; }
  }

И вы хотите получить:

  • Все экраны, которые принадлежат данному списку идентификаторов ролей
  • Все дочерние экраны для заданных экранов, где IsCheck равно false
  • Все дочерние экраны, которые не относятся к RoleScreens таблице

Короче говоря, он получает любой экранэто обозначено в списке идентификаторов ролей и его дочерних экранов.Этот вопрос, однако, может в конечном итоге привести к появлению дочерних экранов дочерних экранов, родительские элементы которых находятся в списке (проблема рекурсии).Однако, если вас устраивают только непосредственные дети, этот запрос удовлетворит вашу потребность:

  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();

Отказ от ответственности: Я на самом деле не проверял запрос.Возьмите это с зерном и большим количеством соли.Я надеюсь, что кто-то может придумать лучший запрос.

0 голосов
/ 22 мая 2018

Проблема здесь

(x.RoleScreens.Any(y => x.IsCheck== false && y.ScreenID == x.ParentID && listUserRoleIDs.Any(z => z == y.RoleID)))

Я не совсем уверен, что вы хотите, но если вы хотите, как вы написали, и хотите ЛЮБОГО ребенка, тогда должно быть:

(x.RoleScreens.Any(y => x.IsCheck== false && y.ScreenID == x.ParentID))

, так как listUserRoleIDs.Any (z => z == y.RoleID) отфильтровывает всех детей, у которых нет RoleID.


, с другой стороны, если вы хотите вседети экранов, у которых есть роль, тогда, вероятно, лучше разделить ее на две части:

var Parents = this.context.Screens.Where(x => (x.IsActive == true) && 
                                    (x.RoleScreens.Any(y => listUserRoleIDs.Any(z => z == y.RoleID))));

var Children = this.context.Screens.Where(x => (x.IsActive == true) && (x.IsCheck== false) && (Parents.Any(y => x.ParentID == y.ScreenID)));

var List = Parents.Union(Children).ToList();
...