7 ответов:
Если вы работаете с вложенным объектом (объект, загруженный из того же экземпляра контекста), вы можете просто использовать:
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<TEntity>( this IDbSet<TEntity> set, params TEntity[] entities ) where TEntity : classкоторый doc:
добавляет или обновляет объекты по ключу при вызове SaveChanges. Аналог к операции "upsert" из терминологии базы данных. Этот метод может быть полезно при заполнении данных с помощью миграции.
ответ комментарий @Smashing1978, я вставлю соответствующие части из ссылке, предоставленной @Колин
задача AddOrUpdate заключается в том, чтобы убедиться, что вы не создаете дубликаты когда вы сеете данные во время разработки.
во-первых, он выполнит запрос в вашей базе данных в поисках записи где все, что вы предоставили в качестве ключа (первый параметр) соответствует сопоставленное значение столбца (или значения), заданное в AddOrUpdate. Так что это это немного рыхлый гусь для соответствия, но прекрасно подходит для посева данные по времени проектирования.
что еще более важно, если совпадение найдено, то обновление обновит все и обнулить все, что не было в вашем AddOrUpdate.
тем не менее, у меня есть ситуация, когда я извлекаю данные из Внешней службы и вставляю или обновляю существующие значения по первичному ключу (а мои локальные данные для потребителей доступны только для чтения)-использую
AddOrUpdateв производстве уже более 6 месяцев и до сих пор никаких проблем.
Если вы знаете, что используете один и тот же контекст и не отсоединяете какие-либо сущности, вы можете сделать общую версию следующим образом:
public void InsertOrUpdate<T>(T entity, DbContext db) where T : class { if (db.Entry(entity).State == EntityState.Detached) db.Set<T>().Add(entity); // If an immediate save is needed, can be slow though // if iterating through many entities: db.SaveChanges(); }
dbконечно, может быть поле класса, или метод может быть сделан статическим и расширением, но это основы.
магия происходит при вызове
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(); } }если вы не можете проверить
Id = 0чтобы определить, является ли это новый объект или нет, проверьте ответ Ладислава Мрнка.
ответ Ладислава был близок, но мне пришлось сделать несколько изменений, чтобы заставить это работать в EF6 (база данных-первая). Я расширил свой контекст данных с помощью метода on 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); } } [....]
вставить еще обновить оба
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. И вы вручную выберете, какие объекты должны быть удалены, если они больше не существуют.пример:
допустим, у меня есть
Comments