Некоторое время назад я хотел реализовать метод, который мог бы определить, выполнять ли вставку или обновление данного объекта, поэтому мне не нужно было раскрывать методы «Вставка» и «Обновление», а просто простой «InsertOrUpdate». ".
Часть кода, которая выясняет, является ли сущность новой или нет, такова:
public virtual T GetEntityByPrimaryKey<T>(T entity) where T : class
{
var entityType = entity.GetType();
var objectSet = ((IObjectContextAdapter)this.DatabaseContext).ObjectContext.CreateObjectSet<T>();
var keyNames = objectSet.EntitySet.ElementType.KeyMembers.Select(edmMember => edmMember.Name);
var keyValues = keyNames.Select(name => entityType.GetProperty(name).GetValue(entity, null)).ToArray();
return this.DatabaseContext.Set<T>().Find(keyValues);
}
И метод InsertOrUpdate таков:
public virtual T InsertOrUpdate<T>(T entity) where T : class
{
var databaseEntity = this.GetEntityByPrimaryKey(entity);
if (databaseEntity == null)
{
var entry = this.DatabaseContext.Entry(entity);
entry.State = EntityState.Added;
databaseEntity = entry.Entity;
}
else
{
this.DatabaseContext.Entry(databaseEntity).CurrentValues.SetValues(entity);
}
return databaseEntity;
}
Теперь этот подход творит чудеса, пока «первичный ключ» объекта определяется кодом. Допустимыми примерами являются GUID, алгоритмы HI-LO, естественные ключи и т. д.
Это, однако, ужасно нарушено для сценария «идентификация, сгенерированная базой данных», и причина довольно проста: поскольку мой «Id» в коде будет равен 0 для всех объектов, которые я собираюсь вставить, метод будет учитывать их одинаковый. Если я добавлю 10 объектов, первый будет "новым", а следующие девять - "уже существующими". Это связано с тем, что метод «Найти» EF считывает данные из объектного контекста и только в том случае, если он отсутствует, он переходит в базу данных для выполнения запроса.
После первого объекта будет отслеживаться объект данного типа с Id 0. Последовательные вызовы приведут к «обновлению», и это просто неправильно.
Теперь я знаю, что идентификаторы, сгенерированные базой данных, являются злом и абсолютно не подходят для любого ORM, но я застрял с ними, и мне нужно либо исправить этот метод, либо полностью удалить его и вернуться к отдельным методам «Вставить» и «Обновить». и делегируйте вызывающей стороне задачу, чтобы определить, что делать. Поскольку у нас есть сильно развязанное решение, я бы предпочел этого не делать.
Если кто-нибудь может помочь и найти способ исправить метод GetEntityByPrimaryKey, это было бы здорово.
Спасибо.