У меня есть объект, который не связан с моим dbcontext. Я хочу изменить это. Однако к dbcontext уже прикреплен другой экземпляр того же объекта. Если я просто добавлю свою новую сущность, я получаю ошибку, что существо с одинаковым первичным ключом уже прикреплена.
я попробовал несколько разных вариантов удаления старого объекта от dbcontext без каких-либо успехов. Как я могу заменить старый экземпляр новым?
Примечание. Я не хочу копировать значения, я хочу прикрепить этот самый экземпляр моего нового объекта на dbcontext.
var entity = new MyEntity { Id = 1 };
var logicalDuplicate = dbcontext.Set<MyEntity >().Local
.FirstOrDefault(e => e.Equals(entity));
if (logicalDuplicate != null)
{
// remove logicalDuplicate from dbcontext
}
dbcontext.MyEntity.Attach(entity);
Для пояснения: я переопределил Equals, чтобы проверить на Id вместо ссылки.
Ответ 1 · рейтинг 10 · Vitaliy Smolyakov
Попробуй это:
if (logicalDuplicate != null)
{
dbcontext.Entry(logicalDuplicate).State = EntityState.Detached;
dbcontext.MyEntity.Attach(entity);
dbcontext.Entry(entity).State = EntityState.Modified;
}
else
{
dbcontext.MyEntity.Add(entity);
}
Как получить связанные записи
Я исследовал это и хочу поделиться своими результатами. Я использовал отражение как короткий способ получить имена свойств объекта. Но это можно получить без размышлений, как уже упоминал @Florian Haider. Вы можете использовать Ответ и это а>.
// Found loaded related entries that can be detached later.
private HashSet<DbEntityEntry> relatedEntries;
private DbContext context;
private List<string> GetPropertiesNames(object classObject)
{
// TODO Use cache for that.
// From question https://stackoverflow.com/questions/5851274/how-to-get-all-names-of-properties-in-an-entity
var properties = classObject.GetType().GetProperties(BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance);
return properties.Select(t => t.Name).ToList();
}
private void GetRelatedEntriesStart(DbEntityEntry startEntry)
{
relatedEntries = new HashSet<DbEntityEntry>();
// To not process start entry twice.
relatedEntries.Add(startEntry);
GetRelatedEntries(startEntry);
}
private void GetRelatedEntries(DbEntityEntry entry)
{
IEnumerable<string> propertyNames = GetPropertiesNames(entry.Entity);
foreach (string propertyName in propertyNames)
{
DbMemberEntry dbMemberEntry = entry.Member(propertyName);
DbReferenceEntry dbReferenceEntry = dbMemberEntry as DbReferenceEntry;
if (dbReferenceEntry != null)
{
if (!dbReferenceEntry.IsLoaded)
{
continue;
}
DbEntityEntry refEntry = context.Entry(dbReferenceEntry.CurrentValue);
CheckReferenceEntry(refEntry);
}
else
{
DbCollectionEntry dbCollectionEntry = dbMemberEntry as DbCollectionEntry;
if (dbCollectionEntry != null && dbCollectionEntry.IsLoaded)
{
foreach (object entity in (ICollection)dbCollectionEntry.CurrentValue)
{
DbEntityEntry refEntry = context.Entry(entity);
CheckReferenceEntry(refEntry);
}
}
}
}
}
private void CheckReferenceEntry(DbEntityEntry refEntry)
{
// Add refEntry.State check here for your need.
if (!relatedEntries.Contains(refEntry))
{
relatedEntries.Add(refEntry);
GetRelatedEntries(refEntry);
}
}
Ответ 2 · bwyn
Редактировать strong> Это находит оригинальный продукт, удаляет его и добавляет новый:
static void UpdateDatabase()
{
Context context = new Context();
Product product1 = context.Products.Find(1);
context.Products.Remove(product1);
Product product2 = new Product(){ProductId = 1, Name = "Product2"};
context.Products.Add(product2);
context.SaveChanges();
}
Ответ 3 · рейтинг -1 · Akshay Bobade
Лучший способ решить эту проблему
DB - это мой объект базы данных
UpdatePrice - это мой объект объекта базы данных
- мой старый объект объекта базы данных
db.Entry(updateprice).CurrentValues.SetValues(ep);