2016-08-31 5 views
0

Я пытаюсь реализовать свой собственный AddOrUpdate, так как Entity Framework не содержит эту функцию. (И мне это нужно)AddOrUpdate в Entity Framework 7

Я знаю, что здесь есть похожие вопросы, но ответа нет или это была другая проблема.

Итак, я пытаюсь реализовать часть обновления. Это мой код:

  • @this: мой DbSet записей в базе данных
  • параметр: атрибут для проверки в БД существует ли уже на запись
  • записи: Все записи либо добавить или обновить

public static void AddOrUpdate<T>(this DbSet<T> @this, Func<T, object> parameter, params T[] entries) where T: class, IEntity 
{ 
    IEnumerable<object> keysExisting = @this.Select(parameter); 

    foreach (T entry in entries) 
    { 
     bool entryExistsAlready = keysExisting.Contains(parameter.Invoke(entry)); 
     if (!entryExistsAlready) 
     { 
      @this.Add(entry); 
      return; 
     } 
     entry.Id = @this.First(w => parameter.Invoke(w).Equals(parameter.Invoke(entry))).Id; 
     @this.Attach(entry); 
     @this.Update(entry); 
    } 
} 

и для завершения информации, это, как я вызываю метод (Там же уже ApplicationUser хранится в БДЕ, с электронной почтой «[email protected]»):

db.ApplicationUsers.AddOrUpdate(s => s.Email, 
     new ApplicationUser{Email="[email protected]", Attribute="modified attribute"} 
     ); 

Я попытался с прикреплением записи и без крепления. Я всегда получаю следующее исключение (или на Attach() или, если не прикрепление, на Update():

InvalidOperationException: экземпляр типа объекта «ApplicationUser» не может быть отслежены, так как другой экземпляр этого типа с тем же key, уже отслеживается. При добавлении новых объектов для большинства типов ключей будет создано уникальное временное ключевое значение, если ключ не установлен (т. е. если для свойства ключа назначено значение по умолчанию для его типа). Если вы явно устанавливаете ключ значения для новых объектов, убедитесь, что они не сталкиваются с существующими объектами или временными значениями, сгенерированными для других новых объектов. При присоединении существующих объектов убедитесь, что к контексту привязан только один экземпляр объекта с заданным значением ключа.

Любая идея, как я могу обновить свои записи?

обновление:

Я уже пытался с отражением, просто установив все значения из каждого свойства, но ApplicationUser например имеет свойство Role, которое невозможно записать. Поэтому я потерял бы данные из своего метода-вызова.

+0

Вы можете получить сущность из базы данных, а затем присвоить измененные свойства от входа к этому объекту и попробовать сделать то же самое. – divya

+0

@divya yes, но это своего рода метод 'Seed()', где я должен давать полные объекты. Я не всегда знаю, какие свойства меняются. –

+0

Затем вам нужно назначить все свойства ... Пожалуйста, обратитесь к этому: http://www.entityframeworktutorial.net/EntityFramework4.3/update-entity-using-dbcontext.aspx – divya

ответ

5

Используя соглашение, что если все свойства, которые составляют первичный ключ Субъекта имеет значение по умолчанию (0, NULL и т.д.), то объект является новым в противном случае она уже существует:

public TEntity AddOrUpdate<TEntity>(DbContext context, TEntity entity) 
    where TEntity : class 
{ 
    context.Entry(entity).State = 
     context.KeyValuesFor(entity).All(IsDefaultValue) 
      ? EntityState.Added 
      : EntityState.Modified; 

    return entity; 
} 

private static bool IsDefaultValue(object keyValue) 
{ 
    return keyValue == null 
      || (keyValue.GetType().IsValueType 
       && Equals(Activator.CreateInstance(keyValue.GetType()), keyValue)); 
} 

Ссылка:

https://blog.oneunicorn.com/2012/05/03/the-key-to-addorupdate/

+0

очень приятно! ссылка была действительно полезна! –

Смежные вопросы