Entity Framework 4 – AddObject vs Attach

Недавно я работал с Entity Framework 4, и я немного смущен, когда следует использовать ObjectSet.Attach и ObjectSet.AddObject .

Из моего понимания:

  • Используйте «Прикрепить», когда сущность уже существует в системе
  • Используйте «AddObject» при создании совершенно нового объекта

Итак, если я создаю нового Человека , я делаю это.

var ctx = new MyEntities(); var newPerson = new Person { Name = "Joe Bloggs" }; ctx.Persons.AddObject(newPerson); ctx.SaveChanges(); 

Если я изменяю существующее лицо , я делаю это:

 var ctx = new MyEntities(); var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" }; existingPerson.Name = "Joe Briggs"; ctx.SaveChanges(); 

Имейте в виду, это очень простой пример. На самом деле я использую Pure POCO (без генерации кода), шаблон репозитория (не имеют отношения к ctx.Persons) и Unit of Work (не имеют отношения к ctx.SaveChanges). Но «под обложками», это то, что происходит в моей реализации.

Теперь, мой вопрос – я еще не нашел сценарий, где мне пришлось использовать Attach .

Что мне здесь не хватает? Когда нам нужно использовать Attach?

РЕДАКТИРОВАТЬ

Чтобы уточнить, я ищу примеры того, когда использовать Attach над AddObject (или наоборот).

EDIT 2

Ниже приведен правильный ответ (который я принял), но я подумал, что добавлю еще один пример, где Attach был бы полезен.

В приведенном выше примере для изменения существующего Person фактически выполняются два запроса.

Один для извлечения Person (.SingleOrDefault), а другой для выполнения UPDATE (.SaveChanges).

Если (по какой-то причине), я уже знал, что в системе существует «Joe Bloggs», зачем нужен дополнительный запрос, чтобы получить его первым? Я мог бы это сделать:

 var ctx = new MyEntities(); var existingPerson = new Person { Name = "Joe Bloggs" }; ctx.Persons.Attach(existingPerson); ctx.SaveChanges(); 

Это приведет к выполнению только инструкции UPDATE.

ObjectContext.AddObject и ObjectSet.AddObject :
Метод AddObject предназначен для добавления вновь созданных объектов, которых нет в базе данных. Сущность получит автоматически созданный временный EntityKey, и его EntityState будет установлен в Добавлен . Когда вызывается SaveChanges, для EF будет ясно, что этот объект необходимо вставить в базу данных.

ObjectContext.Attach и ObjectSet.Attach :
С другой стороны, Attach используется для объектов, которые уже существуют в базе данных. Вместо того, чтобы добавлять EntityState к добавлению, присоедините результаты к неизменному объекту EntityState, что означает, что он не изменился, поскольку он был привязан к контексту. Предполагается, что объекты, которые вы прикрепляете, существуют в базе данных. Если вы изменяете объекты после их присоединения, то при вызове SaveChanges значение EntityKey используется для обновления (или удаления) соответствующей строки путем поиска соответствующего идентификатора в таблице db.

Кроме того, используя метод Attach, вы можете определить отношения между сущностями, которые уже существуют в ObjectContext, но которые не были подключены автоматически. В основном основная цель Attach – подключать объекты, которые уже привязаны к ObjectContext, и не являются новыми, поэтому вы не можете использовать Attach для присоединения объектов, EntityState которых добавлен. Вы должны использовать Add () в этом случае.

Например, предположим, что ваш объект Person имеет свойство навигации с именем Addresses, которое представляет собой коллекцию объекта Address . Допустим, вы прочитали оба объекта из контекста, но они не связаны друг с другом, и вы хотите сделать это так:

 var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" }; var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID); existingPerson.Addresses.Attach(myAddress); // OR: myAddress.PersonReference.Attach(existingPerson) ctx.SaveChanges(); 

Это поздний ответ, но он может помочь другим найти это.

В принципе, «отключенная» сущность может возникать при манипулировании сущностью вне области «использования».

 Employee e = null; using (var ctx = new MyModelContainer()) { e = ctx.Employees.SingleOrDefault(emp => emp .....); } using (var ctx2 = new MyModelContainer()) { e; // This entity instance is disconnected from ctx2 } 

Если вы введете другую область «использования», тогда переменная «e» будет отключена, поскольку она принадлежит к предыдущей области «использования», и поскольку предыдущая область «использования» уничтожена, «e» отключается.

Вот как я это понимаю.

Это цитата из программирования Entity Framework: DbContext

Вызов Удаление объекта, не отслеживаемого контекстом, вызовет исключение InvalidOperationException. Entity Framework генерирует это исключение, поскольку неясно, является ли объект, который вы пытаетесь удалить, существующим объектом, который должен быть помечен для удаления, или новый объект, который следует просто игнорировать. По этой причине мы не можем использовать только «Удалить», чтобы пометить отключенный объект как «Удалено»; нам нужно сначала прикрепить его .

 private static void TestDeleteDestination() { Destination canyon; using (var context = new BreakAwayContext()) { canyon = (from d in context.Destinations where d.Name == "Grand Canyon" select d).Single(); } DeleteDestination(canyon); } private static void DeleteDestination(Destination destination) { using (var context = new BreakAwayContext()) { context.Destinations.Attach(destination); context.Destinations.Remove(destination); context.SaveChanges(); } } 

Метод TestDeleteDestination имитирует клиентское приложение, получающее существующий пункт назначения с сервера, и затем передает его методу DeleteDestination на сервере. Метод DeleteDestination использует метод Attach, чтобы контекст знал, что это существующее назначение. Затем метод Remove используется для регистрации существующего адресата для удаления

А как насчет ссылки на первичный ключ вместо привязки?

то есть:

 var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" }; var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID); existingPerson.AddressId = myAddress.Id // not -> existingPerson.Addresses.Attach(myAddress); // OR: myAddress.Person.Id = existingPerson.Id // not -> myAddress.PersonReference.Attach(existingPerson); ctx.SaveChanges(); 
  • Результат запроса нельзя перечислить более одного раза
  • Entity Framework 4 / POCO - С чего начать?
  • Самый эффективный метод дерева привязки с использованием Entity Framework
  • Шаблон хранилища, POCO и бизнес-объекты
  • Есть ли в Entity Framework 4 Code First поддержка генераторов идентификаторов, таких как NHibernate?
  • Entity Framework создает множественное имя таблицы, но представление ожидает уникальное имя таблицы?
  • Указанное именованное соединение либо не находится в конфигурации, не предназначено для использования с поставщиком EntityClient, либо недействительно
  • Entity Framework 4 Удалить объект из коллекции объектов
  • LEFT JOIN в LINQ для объектов?
  • Entity Framework объединяет 3 таблицы
  • Код элемента Entity Framework Первый метод AddOrUpdate insert Дублирующие значения
  • Interesting Posts

    Локализация значений enums в наборе ресурсов

    WaitForInputIdle не работает для запуска программной программы mspaint

    Что такое тип данных uintptr_t

    Нарушение спящего режима с помощью orphanRemoval

    Почему (int) (объект) 10m бросает исключение «Указанный приведение недействителен»?

    Windows 8 спит после 1 минуты бездействия

    ChromeWebDriver – неизвестная ошибка: Chrome не удалось запустить: crashed

    Завершение установки установщика Windows 7 (до фактической установки)

    Почему static_cast не может использоваться для down-cast, когда задействовано виртуальное наследование?

    Android 4.3 Bluetooth Низкая энергия нестабильная

    Изменить расширяемый индикатор в ExpandableListView

    Как настроить сериализацию списка объектов JAXB для JSON?

    Понимание регулярного выражения в Java: split (“\ t”) vs split (“\\ t”) – когда они оба работают, и когда они должны использоваться

    Почему System.arraycopy является родным в Java?

    Как ввести значения RGB в Interface Builder?

    Давайте будем гением компьютера.