Подтвердить что ты не робот

Поиск контекстов платформы Entity Framework

В связи с различными вопросами, заданными здесь и другими форумами, я пришел к выводу, что понятия не имею, что я делаю, когда речь идет о объектах контекста сгенерированных объектов в Entity Framework.

В качестве фона у меня много опыта с использованием LLBLGen Pro, а для Entity Framework мне около трех недель.

Предположим, что у меня есть контекст, называемый "myContext". В моей модели есть таблица/объект под названием Employee, поэтому теперь у меня есть myContext.Employees. Я предполагаю, что это означает, что это свойство представляет собой набор сущностей Employee в моем контексте. Однако я ошибаюсь, поскольку я могу добавить новый объект в контекст с помощью:

myContext.Employees.AddObject(new Employee());

и этот новый объект Employee не отображается в myContext.Employees. Из того, что я собираю, единственный способ найти этот добавленный объект - это отслеживать его, скрываясь в myContext.ObjectStateManager. Это звучит для меня как набор myContext.Employees - это фактически не набор сущностей Employee в контексте, а скорее какое-то представление сущностей Employee, которые существуют в базе данных.

Чтобы добавить к этой путанице, скажем, я смотрю на отдельную сущность сотрудника. Существует объект проекта, который имеет отношения M: 1 с Employee (у сотрудника может быть несколько проектов). Если я хочу добавить новый проект к конкретному сотруднику, я просто делаю:

myEmployee.Projects.Add(new Project());

Отлично, это фактически добавляет проект в коллекцию, как я ожидал. Но это летит прямо перед тем, как работают свойства ObjectSet вне контекста. Если я добавлю новый проект в контекст с помощью:

myContext.Projects.AddObject(new Project());

это не изменяет набор проектов.

Я был бы очень признателен, если бы кто-то объяснил мне это. Кроме того, мне действительно нужна коллекция всех сотрудников (или проектов) в контексте, и я хочу, чтобы она была доступна как свойство контекста. Возможно ли это с помощью EF?

4b9b3361

Ответ 1

An ObjectSet - это запрос. Как и все в LINQ, он ленив. Он ничего не делает, пока вы не перечислите его или не вызовите метод типа .Count(), после чего запускается запрос базы данных, и любые возвращенные объекты объединяются с теми, которые уже находятся в контексте.

Итак, вы можете сделать что-то вроде:

var activeEmployees = Context.Employees.Where(e => e.IsActive)

... без выполнения запроса.

Вы также можете написать следующее:

var orderedEmployees = activeEmployees.OrderBy(e => e.Name);

... снова, без выполнения запроса.

Но если вы посмотрите на набор:

var first = orderedEmployees.First();

... затем выполняется запрос БД. Это является общим для всех LINQ.

Если вы хотите перечислить объекты уже в контексте, вам нужно посмотреть на ObjectStateManager. Итак, для сотрудников вы можете:

var states = EntityState.Added || EntityState.Deleted || // whatever you need
var emps = Context.ObjectStateManager.GetObjectStateEntries(states)
                                     .Select(e => e.Entity)
                                     .OfType<Employee>();

Обратите внимание, что, хотя это работает, я не рекомендую работать. Как правило, вы не хотите, чтобы ваши объекты ObjectContexts были долговечными. Для этого и по другим причинам они не подходят для универсального контейнера объектов. Для этого используйте обычные типы списков. Точнее думать об ObjectContext как о единице работы. Как правило, в подразделении работы вы уже знаете, с какими экземплярами вы работаете.