Entity Framework - Запросы из ObjectContext против Запроса из свойства навигации - PullRequest
3 голосов
/ 18 июля 2011

Я заметил, что в зависимости от того, как я извлекаю данные из моей модели Entity Framework, я получаю разные типы результатов. Например, при получении списка сотрудников в определенном отделе:

Если я получаю напрямую из ObjectContext, я получаю IQueryable<Employee>, который на самом деле System.Data.Objects.ObjectQuery<Employee>:

var employees = MyObjectContext.Employees.Where(e => e.DepartmentId == MyDepartment.Id && e.SomeCondtition)

Но если я использую свойство навигации MyDepartment, я получу IEnumerable<Employee>, что на самом деле System.Linq.WhereEnumerableIterator<Employee> (закрытый класс в System.Linq.Enumerable):

var employees = MyDeparment.Employees.Where(e => e.SomeCondtition)

В следующем коде я интенсивно использую employees в нескольких запросах LINQ (Where, OrderBy, First, Sum и т. Д.)

Должен ли я учитывать, какой метод запроса я использую? Будет ли разница в производительности? Использует ли последний отложенное исполнение? Является ли одна лучшая практика? Или это не имеет значения?

Я спрашиваю об этом, потому что с момента установки ReShaper 6 я получаю много возможных многократных перечислений предупреждений IEnumerable при использовании последнего метода, но ни одного при использовании прямых запросов. Я использую последний метод чаще, просто потому, что писать гораздо чище, и мне интересно, действительно ли это дало отрицательный эффект!

1 Ответ

2 голосов
/ 18 июля 2011

Очень большая разница.

Если вы используете первый подход, у вас есть IQueryable = дерево выражений, и вы все равно можете добавлять другие выражения, и только при выполнении запроса (отложенное выполнение) дерево выражений будет преобразовано в SQL и выполнено вбаза данных.Так что, если вы используете свой первый пример и добавите .Sum чего-то, вы действительно выполните операцию в базе данных, и она передаст только одно число обратно вашему приложению.Это linq-to-entity.

Второй пример используется в сборе памяти.Свойство навигации не представляет IQueryable (дерево выражений).Все команды linq обрабатываются как linq-to-objects = все записи, представляющие связанные данные в свойстве навигации, должны быть сначала загружены из базы данных в ваше приложение, и все операции выполняются в памяти вашего сервера приложений.Вы можете загрузить свойство навигации быстро (с помощью Include), явно (с помощью Load) или лениво (это выполняется автоматически при первом доступе к свойству, если включена отложенная загрузка).Поэтому, если вы хотите получить сумму чего-либо, этот сценарий требует, чтобы вы загрузили все данные из базы данных, а затем выполнили операцию локально.

...