Почему работает ChangeTracker.Загрузить() не загружает все мои навигационные свойства?

#c# #.net-core #entity-framework-core

Вопрос:

У меня есть коллекция сущностей, на которые ссылается моя Company сущность, как это

 public sealed class Company 
{
    private readonly List<CompanyJobCategory> _jobCategories = new();
    public IReadOnlyCollection<CompanyJobCategory> JobCategories => _jobCategories.AsReadOnly();
}

public sealed class CompanyJobCategory
{
    public CompanyJobCategory(int jobCategoryId, Guid companyId)
    {
        JobCategoryId = jobCategoryId;
        CompanyId = companyId;
    }
    
    public int JobCategoryId { get; private set; }
    public JobCategory JobCategory { get; private set; }
    public Guid CompanyId { get; private set; }
}

public sealed class JobCategory
{
    // the stuff I need is here
}
 

Все работает нормально, но теперь мне нужно убедиться, что JobCategory эти свойства навигации доступны в какой-то момент, прежде чем звонить DbContext.SaveChanges()

Я хватаю сущность вот так

 var entry = DbContext.ChangeTracker
    .Entries<Company>()
    .FirstOrDefault(entry => entry.Entity.Id == id)!;
 

Но могу видеть , что для каждого entry.Entity.JobCategories JobCategory из них всегда равно нулю (из-за того, как я инициализировал сущность)

Я думал, что смогу сделать что-то вроде

 DbContext.ChangeTracker.Entries<Company>().First().Collection(x => x.JobCategories).Load();
 

но это не заполняет дочерние навигационные реквизиты

Я также попытался установить IsLoaded значение false перед вызовом Load() , но это не помогло

Самое странное, что я заметил, это то, что иногда некоторые из этих дочерних сущностей будут полностью загружены, если я загляну внутрь записи.Коллекции(x => x.Категории заданий)[0].Категория заданий> но нет никакой разницы в том, как я их добавляю. Как это возможно?

Я также попробовал следующее, которое, похоже, загружает большинство JobCategory ссылок, но все равно некоторые из них отображаются как нулевые — возможно ли это?

 entry.Collection(x => x.JobCategories)
    .Query()
    .Include(y => y.JobCategory)
    .Load();
 

Комментарии:

1.«ссылается на другую сущность под названием JobCategory» — отдельную JobCategory или совокупность JobCategory ? Я предполагаю, что коллекция из чтения вашего вопроса, но она может оказаться полезной, чтобы сделать ее более понятной, пожалуйста.

2. @ErmiyaEskandary CompanyJobCategory содержит ссылку на один JobCategory — это в основном таблица соединений m2m

3. Последний фрагмент (с Query().Include(...).Load() ) — это предполагаемый способ выполнить то, о чем вы просите.

4. @IvanStoev Спасибо, Иван, есть идеи, почему 1 или 2 навигационных реквизита все еще не заполнены? В основном это работает, но некоторые все равно приходят как null, хотя я вижу, что do ссылается на реальную строку во внешней таблице… Хотя это кажется невозможным

Ответ №1:

Вот как я заставил это работать

 // get the entity which is about to be persisted
var entry = DbContext.ChangeTracker
    .Entries<Company>()
    .FirstOrDefault(x => x.Entity.Id == id)!;

// select the ids for the referenced entities I need to load
var jobCategoryIds = entry.Entity.JobCategories
    .Select(x => x.JobCategoryId); 

// load them into into DbContext
await DbContext.Set<JobCategory>()
    .Where(x => jobCategoryIds.Contains(x.Id))
    .LoadAsync();
 

Вместо того, чтобы просто вызывать LoadAsync() отслеживаемую коллекцию, мне нужно загрузить нужные мне ссылочные объекты прямо в DbContext