Обновить строку, если она существует в остальной логике вставки с платформой Entity Framework

Есть ли у кого-нибудь предложения по наиболее эффективному способу реализации логики «обновить строку, если она существует в другом месте», используя Entity Framework?

Если вы работаете с прикрепленным объектом (объектом, загруженным из того же экземпляра контекста), вы можете просто использовать:

if (context.ObjectStateManager.GetObjectStateEntry(myEntity).State == EntityState.Detached) { context.MyEntities.AddObject(myEntity); } // Attached object tracks modifications automatically context.SaveChanges(); 

Если вы можете использовать любые знания о ключе объекта, вы можете использовать что-то вроде этого:

 if (myEntity.Id != 0) { context.MyEntities.Attach(myEntity); context.ObjectStateManager.ChangeObjectState(myEntity, EntityState.Modified); } else { context.MyEntities.AddObject(myEntity); } context.SaveChanges(); 

Если вы не можете определить существование объекта по его идентификатору, вы должны выполнить запрос поиска:

 var id = myEntity.Id; if (context.MyEntities.Any(e => e.Id == id)) { context.MyEntities.Attach(myEntity); context.ObjectStateManager.ChangeObjectState(myEntity, EntityState.Modified); } else { context.MyEntities.AddObject(myEntity); } context.SaveChanges(); 

Начиная с платформы Entity Framework 4.3 существует метод AddOrUpdate в пространстве имен System.Data.Entity.Migrations :

 public static void AddOrUpdate( this IDbSet set, params TEntity[] entities ) where TEntity : class 

который по документу :

Добавляет или обновляет объекты по ключу при вызове SaveChanges. Эквивалент операции «upsert» из базы данных. Этот метод может быть полезен при посеве данных с использованием Migrations.


Чтобы ответить на комментарий от @ Smashing1978 , я вставлю соответствующие части из ссылки, предоставленной @Colin

Задача AddOrUpdate заключается в том, чтобы вы не создавали дубликаты при посеве данных во время разработки.

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

Что еще более важно, если совпадение найдено, обновление обновит все и обнуляет любые, которые не были в вашем AddOrUpdate.

Тем не менее, у меня есть ситуация, когда я извлекаю данные из внешней службы и вставляю или обновляю существующие значения с помощью первичного ключа (и мои локальные данные для потребителей доступны только для чтения) – с использованием AddOrUpdate в производстве более 6 месяцев и до сих пор нет проблем.

Если вы знаете, что используете один и тот же контекст и не отсоединяете какие-либо объекты, вы можете сделать такую ​​общую версию:

 public void InsertOrUpdate(T entity, DbContext db) where T : class { if (db.Entry(entity).State == EntityState.Detached) db.Set().Add(entity); // If an immediate save is needed, can be slow though // if iterating through many entities: db.SaveChanges(); } 

Конечно, db может быть полем classа, или метод может быть сделан статическим и расширением, но это основы.

Ответ Ладислава был близок, но мне пришлось сделать пару модификаций, чтобы заставить его работать в EF6 (сначала в базе данных). Я расширил свой контекст данных с помощью метода AddOrUpdate и пока, похоже, хорошо работает с отдельными объектами:

 using System.Data.Entity; [....] public partial class MyDBEntities { public void AddOrUpdate(MyDBEntities ctx, DbSet set, Object obj, long ID) { if (ID != 0) { set.Attach(obj); ctx.Entry(obj).State = EntityState.Modified; } else { set.Add(obj); } } [....] 

Магия происходит при вызове SaveChanges() и зависит от текущего EntityState . Если объект имеет EntityState.Added , он будет добавлен в базу данных, если он имеет EntityState.Modified , он будет обновлен в базе данных. Таким образом, вы можете реализовать метод InsertOrUpdate() следующим образом:

 public void InsertOrUpdate(Blog blog) { using (var context = new BloggingContext()) { context.Entry(blog).State = blog.BlogId == 0 ? EntityState.Added : EntityState.Modified; context.SaveChanges(); } } 

Подробнее о EntityState

Если вы не можете проверить Id = 0 чтобы определить, является ли это новой сущностью или нет, проверьте ответ Ladislav Mrnka .

Вставьте еще обновление

 public void InsertUpdateData() { //Here TestEntities is the class which is given from "Save entity connection setting in web.config" TestEntities context = new TestEntities(); var query = from data in context.Employee orderby data.name select data; foreach (Employee details in query) { if (details.id == 1) { //Assign the new values to name whose id is 1 details.name = "Sanjay"; details. Surname="Desai"; details.address=" Desiwadi"; } else if(query==null) { details.name="Sharad"; details.surname=" Chougale "; details.address=" Gargoti"; } //Save the changes back to database. context.SaveChanges(); } 

На мой взгляд, стоит сказать, что с недавно выпущенным EntityGraphOperations для Entity Framework Code First вы можете спасти себя от написания повторяющихся кодов для определения состояний всех объектов на графике. Я являюсь автором этого продукта. И я опубликовал его в github , code-project ( включает пошаговую демонстрацию и образец проекта готов к загрузке) и nuget .

Он автоматически установит состояние объектов для Added или Modified . И вы вручную выберете, какие сущности должны быть удалены, если они больше не существуют.

Пример:

Допустим, у меня есть объект Person . Person может быть много телефонов, Документ и может иметь супруга.

 public class Person { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string MiddleName { get; set; } public int Age { get; set; } public int DocumentId {get; set;} public virtual ICollection Phones { get; set; } public virtual Document Document { get; set; } public virtual PersonSpouse PersonSpouse { get; set; } } 

Я хочу определить состояние всех объектов, которые включены в график.

 context.InsertOrUpdateGraph(person) .After(entity => { // Delete missing phones. entity.HasCollection(p => p.Phones) .DeleteMissingEntities(); // Delete if spouse is not exist anymore. entity.HasNavigationalProperty(m => m.PersonSpouse) .DeleteIfNull(); }); 

Также, как вы знаете, уникальные ключевые свойства могут играть роль при определении состояния объекта Phone. Для таких специальных целей у нас есть class ExtendedEntityTypeConfiguration<> , который наследуется от EntityTypeConfiguration<> . Если мы хотим использовать такие специальные конфигурации, мы должны наследовать наши classы сопоставления из ExtendedEntityTypeConfiguration<> , а не EntityTypeConfiguration<> . Например:

 public class PhoneMap: ExtendedEntityTypeConfiguration { public PhoneMap() { // Primary Key this.HasKey(m => m.Id); … // Unique keys this.HasUniqueKey(m => new { m.Prefix, m.Digits }); } } 

Это все.

  • Асинхронная операция Entity Framework занимает в десять раз больше времени
  • Как добавить ROW_NUMBER в запрос LINQ или Entity?
  • В чем разница между .ToList (), .AsEnumerable (), AsQueryable ()?
  • Сначала создайте код, многие для многих, с дополнительными полями в таблице объединений
  • Как создать сопоставление «многие-ко-многим» в Entity Framework?
  • Oracle.ManagedDataAccess.EntityFramework - ORA-01918: пользователя 'dbo' не существует
  • Ошибка: в этом контексте поддерживаются только примитивные типы или типы перечислений EF
  • Как выполнить запрос «in» в структуре сущностей?
  • Как сравнивать только даты без времени в типах DateTime в Linq to SQL с Entity Framework?
  • Необработанный SQL-запрос Entity framework
  • Использование Entity Framework с частной компактной установкой SQL Compact
  • Interesting Posts

    Как проверить, зарегистрирован ли пользователь в FB SDK 4.0 для Android?

    Несколько строк заголовка JTable

    Почему я не могу использовать оператор switch на String?

    Как добавить Drop Down List после вставки новой строки в VBA

    Как запросить текущий IP-адрес iPhone?

    В Mac OS, что такое сочетание клавиш для переключения между окнами одного и того же приложения?

    Как проводить поиск Accent Sensitive в MySql

    Как заставить git работать с pagent (putty) в Windows?

    jqgrid: как установить параметры панели инструментов на основе значения столбца в строке

    Какое допустимое магнитное поле (в Тесле) для жесткого диска?

    Создать сценарий в окне окна, который извлекает данные из окна Linux, выполняя cmds

    Стилирование Google Maps InfoWindow

    Получение списка активных активных streamов в .NET?

    Как я могу взять вывод сценария оболочки и поместить его в файл в командной строке?

    Контролировать использование полосы пропускания каждого компьютера в сети

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