Entity Framework Core: как убедиться, что свойство навигации загружено? - PullRequest
1 голос
/ 03 августа 2020

Допустим, у меня есть следующие модели:

public class Subject
{
    private List<SubjectResponse> responses;

    public int Id { get; private set; }

    public IEnumerable<SubjectResponse> Responses => responses.ToList();

    public void Foo()
    {
        // How do I check here if Responses fully has been loaded?

        foreach (var response in Responses)
        {
            // ...
        }
    }
}

public class SubjectResponse
{
    public int Id { get; private set; }
}

Как проверить, все ли ответы загружены в Foo()? Я бы, вероятно, проверил if (Responses is null), но это не сработает во всех случаях.

Вот минимальный пример того, что может быть неправильным. В реальном приложении ответы могут быть загружены в совершенно другое место. Но h Это показывает, как EF может исправить ответы, чтобы он мог содержать записи, но не все записи.

public async Task Bar()
{
    var response = await dbContext.SubjectResponses.SingleAsync(s => s.Id == 1);
    var subject = await dbContext.Subjects.SingleAsync(s => s.Id == 1);
    subject.Foo();
    // subject.Responses now has a count if 1, when there might actually be more responses.
}

Я не хочу использовать отложенную загрузку из-за влияния на производительность (и потому что отложенная загрузка не загружает связанные объекты asyn c). Активная и явная загрузка - это нормально.

Изменить: в основном я ищу способ проверить, полностью ли загружено свойство навигации, чтобы я мог загрузить его, которого не было.

1 Ответ

1 голос
/ 03 августа 2020

Вы не можете определить, все ли связанные сущности прошли через Entity Framework.

То, что вы показываете, работает, потому что сущность из dbContext.SubjectResponses.SingleAsync(s => s.Id == 1) имеет SubjectId 1, и будет кэшироваться, и последовательно быть прикрепленным к результату dbContext.Subjects.SingleAsync(s => s.Id == 1).

Ни EF, ни ваш код не могут знать, что все SubjectResponses с SubjectId из 1 были загружены из базы данных, поэтому вам придется явно загрузить их :

var subject = await dbContext.Subjects.SingleAsync(s => s.Id == 1);
await dbContext.Entity(subject)
               .Reference(s => s.responses)
               .LoadAsync();

Но вы не можете этого сделать, поскольку Subject.responses является частным, поэтому у вас будет чтобы сделать это из метода Foo() вашей сущности, и вам придется внедрить свой DbContext в свою сущность, и это просто превратится в гигантский беспорядок.

Почему бы просто не сделать это прагматично, make Responses publi c auto-property и Include() заранее заданные связанные объекты:

var subject = await dbContext.Subjects.Include(s => s.Responses).SingleAsync(s => s.Id == 1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...