Entity Framework - Запросы из ObjectContext против Запроса из свойства навигации

Я заметил, что в зависимости от того, как я извлекаю данные из моей модели 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 ответ

Решение

Здесь очень большая разница.

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

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

Другие вопросы по тегам