Поиск контекстов 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, существующих в базе данных.

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

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

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

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

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

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

1 ответ

Решение

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 как о единице работы. Как правило, в единице работы вы уже знаете, с какими экземплярами вы работаете.

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