EF core - parent.InverseParent возвращает нуль для некоторых строк - PullRequest
1 голос
/ 06 мая 2019

У меня есть таблица Category, и у нее есть Parent Category, я пытаюсь перебрать все категории и получить родительские категории с помощью Inverse Parent, но некоторые из них возвращаются без обратных родителей по неизвестной причине.

Categories.cs

 public partial class Categories
{
    public Categories()
    {
        InverseParent = new HashSet<Categories>();   
    }

    public int Id { get; set; }
    public int? ParentId { get; set; }
    public DateTime CreateDate { get; set; }
    public bool? Status { get; set; }

    public virtual Categories Parent { get; set; }

    public virtual ICollection<Categories> InverseParent { get; set; }

}

Вот как я пытаюсь выполнить их итерацию для создания элементов списка выбора:

  var parentCategories = await _context.Categories.
                                                      Include(x => x.Parent).
                                                      Where(x => x.Status == true).
                                                      Where(x => x.Parent != null).
                                                      Select(x => x.Parent).
                                                      Distinct().
                                                      ToListAsync();

                foreach (var parent in parentCategories)
                {
                    SelectListGroup group = new SelectListGroup() { Name = parent.Id.ToString() };
                    foreach (var category in parent.InverseParent)
                    {
                        categories.Add(new SelectListItem { Text = category.Id.ToString(), Value = category.Id.ToString(), Group = group });
                    }
                }

Так что проблема в том, что некоторые из моих родительских категорий возвращают все своидетские категории, а некоторые нет, и я не знаю, почему.

Ответы [ 2 ]

2 голосов
/ 06 мая 2019

Существует несколько проблем с этим кодом, все они имеют объяснения в разделе Загрузка связанных данных документации.

Во-первых, вы не просили EF Core включить InverseParent так что логичнее ожидать, что оно будет всегда null.

То, что вы получите, является результатом следующего поведения Eager Loading :

Совет

Entity Framework Core автоматически исправит свойства навигации для любых других объектов, которые ранее были загружены в экземпляр контекста.Таким образом, даже если вы не включите данные для свойства навигации в явном виде, свойство все равно может быть заполнено, если ранее были загружены некоторые или все связанные объекты.

Второе, поскольку запрос изменяетсяэто начальная форма (Select, Disctinct), она попадает в категорию Ignored Включает в себя категорию .

С учетом сказанного вы должны построить запрос другим способом - начиная непосредственно с parentкатегории и в том числе InverseParent:

var parentCategories = await _context.Categories
    .Include(x => x.InverseParent)
    .Where(x => x.InverseParent.Any(c => c.Status == true)) // to match your query filter
    .ToListAsync();
0 голосов
/ 06 мая 2019

Пока вы включаете Include(x => x.Parent), похоже, вы не делаете то же самое для InverseParent. Это может повлиять на ваши результаты именно так, как вы описываете. Будет ли в том числе это исправить?

parentCategories = await _context.Categories.
                                                      Include(x => x.Parent).
                                                      Include(x => x.InverseParent).
                                                      Where(x => x.Status == true).
                                                      Where(x => x.Parent != null).
                                                      Select(x => x.Parent).
                                                      Distinct().
                                                      ToListAsync();

                foreach (var parent in parentCategories)
                {
                    SelectListGroup group = new SelectListGroup() { Name = parent.Id.ToString() };
                    foreach (var category in parent.InverseParent)
                    {
                        categories.Add(new SelectListItem { Text = category.Id.ToString(), Value = category.Id.ToString(), Group = group });
                    }
                }

UPD: так как вы все равно выбираете x => x.Parent, может потребоваться использовать метод ThenInclude().

...