Почему я получаю исключение NullReferenceException при использовании ToDictionary в запросе Entity Framework? - PullRequest
0 голосов
/ 26 сентября 2018

Я очень удивлен, кажется, что мои лямбда-выражения выполняются как код C # вместо преобразования в SQL.

Если это действительно так, то это немного грустно.Например:

context.Set<Post>().ToDictionary(post => post.Id, post => post.Comments.Count())

Этот код, очевидно, сначала загрузит сообщения в объекты C #, а затем посчитает комментарии.Я пришел к такому выводу, потому что в подобном куске реального кода у меня был NullReferenceException, потому что post.Comments был нулевым (обратите внимание, что в моем коде сообщения были загружены без Comments отношение непосредственно перед выполнением этой строки кода).

Тогда использование этого будет гораздо более эффективным:

context.Set<Post>()
    .Select(post => new { Key = post.Id, Value = post.Comments.Count() })
    .ToDictionary(entry => entry.Key, entry => entry.Value)

Поскольку я считаю, что этот код достаточно универсален для работы в любой ситуации,Интересно,

  • Правильно ли я понимаю, что происходит?
  • Почему он не был реализован как универсальное решение для ToDictionary, как это было для ToArrayи ToList?

1 Ответ

0 голосов
/ 26 сентября 2018

Нет метода Queryable.ToDictionary (отметьте здесь ), поэтому ToDictionary принимает context.Set<Post>() как IEnumerable.Это означает, что, как вы правильно поняли, context.Set<Post>() сначала оценивается, а затем обрабатывается в памяти.

Это крайне неэффективно, потому что теперь для каждого Post комментарии загружаются отдельным запросом, если они ленивые.загрузка включена, в противном случае Post.Comments - это null.

Так что проецирование на анонимный тип является единственным вариантом, позволяющим сделать это эффективно.

...