Как мне сохранить запись в ADO.NET EF 4.1? - PullRequest
13 голосов
/ 28 июня 2011

Я пытаюсь сделать что-то действительно простое и не могу найти, как это сделать с помощью Entity Framework 4.1.

Мне нужен метод контроллера, который принимает объект, а затем выполняет UPSERT (вставка или обновление в зависимости от того, существует ли запись в базе данных).

Я использую естественный ключ,поэтому я не могу посмотреть на мое POCO и сказать, новый он или нет.

Вот как я это делаю, и мне кажется, что это неправильно:

[HttpPost]
public JsonResult SaveMyEntity(MyEntity entity)
{            
    MyContainer db = new MyContainer(); // DbContext
    if (ModelState.IsValid)
    {
        var existing =
            db.MyEntitys.Find(entity.MyKey);
        if (existing == null)
        {
            db.MyEntitys.Add(entity);
        }
        else
        {
            existing.A = entity.A;
            existing.B = entity.B;
            db.Entry(existing).State = EntityState.Modified;
        }
        db.SaveChanges();
        return Json(new { Result = "Success" });
    }
}

В идеалевсе это будет примерно так:

db.MyEntities.AddOrModify(entity);

Ответы [ 5 ]

21 голосов
/ 28 июня 2011

К сожалению, нет способа сделать это без запроса базы данных или использования хранимой процедуры.Минималистичный код должен быть:

public void AddOrModify<T>(T entity, string key) where T : class, IEntity // Implements MyKey 
{
     using (var context = new MyContainer())
     {
         if (context.Set<T>().Any(e => e.MyKey == key))
         {
              context.Entry(entity).State = EntityState.Modified;
         } 
         else
         {
              context.Entry(entity).State = EntityState.Added;
         }

         context.SaveChanges();
     }
}
2 голосов
/ 29 ноября 2012

Чтобы выполнить операцию UPSERT, вы можете рассмотреть возможность создания SP, который выполняет MERGE.

http://www.databasejournal.com/features/mssql/article.php/3739131/UPSERT-Functionality-in-SQL-Server-2008.htm

Независимо от того, как вы выбираете операцию, она должна быть атомарной, иначе у вас будет состояние гонки.Вашему SP, вероятно, понадобится ДЕРЖАТЕЛЬ, чтобы аннулировать это ...

http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx

2 голосов
/ 28 июня 2011

на самом деле есть способ сообщить контексту БД, что сущность, которую вы пытаетесь вставить, изменена, и теперь новая

_context.MyEntity.Attach(entity);
_context.MyEntity(entity).State = System.Data.EntityState.Modified;
2 голосов
/ 28 июня 2011

В большинстве случаев вам не нужно явно устанавливать EntityState.Modified, если вы не отключили отслеживание изменений.

Мы приняли решение проверить значение идентификатора объекта:

if (entity.Id == default(int)) {
    // transient entity so insert
} else {
    // update
}
0 голосов
/ 19 ноября 2017

Я знаю, что этот вопрос старый и имеет принятый ответ, но я думаю, что есть лучшее решение: для него не требуется дополнительный интерфейс или тип ключа.

public static class DbSetExtensions
{
    public static EntityEntry<TEnt> AddIfNotExists<TEnt, TKey>(this DbSet<TEnt> dbSet, TEnt entity, Func<TEnt, TKey> predicate) where TEnt : class
    {
        var exists = dbSet.Any(c => predicate(entity).Equals(predicate(c)));
        return exists
            ? null
            : dbSet.Add(entity);
    }

    public static void AddRangeIfNotExists<TEnt, TKey>(this DbSet<TEnt> dbSet, IEnumerable<TEnt> entities, Func<TEnt, TKey> predicate) where TEnt : class
    {
        var entitiesExist = from ent in dbSet
            where entities.Any(add => predicate(ent).Equals(predicate(add)))
            select ent;

        dbSet.AddRange(entities.Except(entitiesExist));
    }
}

Так что позже его можно использовать так:

using (var context = new MyDbContext())
{
    var user1 = new User { Name = "Peter", Age = 32 };
    context.Users.AddIfNotExists(user1, u => u.Name);

    var user2 = new User { Name = "Joe", Age = 25 };
    context.Users.AddIfNotExists(user2, u => u.Age);

    // Adds user1 if there is no user with name "Peter"
    // Adds user2 if there is no user with age 25
    context.SaveChanges();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...