Поиск контекстов Entity Framework - PullRequest
13 голосов
/ 26 апреля 2010

Через различные вопросы, которые я задавал здесь и на других форумах, я пришел к выводу, что понятия не имею, что я делаю, когда дело доходит до созданных объектов контекста сущности в 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, существующих в базе данных.

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

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

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

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

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

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

1 Ответ

16 голосов
/ 27 апреля 2010

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 были долгоживущими. По этой и другим причинам они не очень подходят для того, чтобы быть контейнером объектов общего назначения. Для этого используйте обычные типы List. Более правильно думать о ObjectContext как о единице работы. Обычно в единице работы вы уже знаете, с какими экземплярами вы работаете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...