【发布时间】:2023-03-17 05:53:01
【问题描述】:
在我需要的 WebApi 方法中,如果一个元素不存在,则插入它并在一些操作后更新它。
代码如下:
Entry existingEntry = await _repo.GetEntryByIdAsync(id);
existingEntry = await _repo.AddNewEntryAsync(existingAccred);
// Some code...
// Update
existingAccred.IdField = myField;
await _repo.UpdateEntryAsync(existingEntry);
repo 如下:
public async Task<Entry> GetEntryByIdAsync(int myId)
{
var result = from entry in _ctx.Set<DALENTRY>()
where entry.ID == myId
select new Entry
{
ID = entry.IdEntry,
};
return await result.AsNoTracking().FirstOrDefaultAsync();
}
public async Task<Entry> AddNewEntryAsync(Entry newEntry)
{
DALENTRY entry = new DALENTRY()
{
GUID = newEntry.GUID,
};
_ctx.Add(entry);
await _ctx.SaveChangesAsync();
newEntry.IdEntry = entry.ID;
return newEntry;
}
public async Task<Entry> UpdateEntryAsync(Entry updateEntry)
{
DALENTRY entry = new DALENTRY()
{
ID = updateEntry.IdEntry,
FIELD= updateEntry.IdField,
};
_ctx.Update(entry);
await _ctx.SaveChangesAsync();
return updateEntry;
}
但是当我执行更新时,我得到的是以下错误:
处理请求时发生未处理的异常。
InvalidOperationException:实体类型“DALENTRY”的实例不能 被跟踪,因为另一个具有相同键值的实例 {'ID'} 已被跟踪。附加现有实体时, 确保只有一个具有给定键值的实体实例 随附的。考虑使用 'DbContextOptionsBuilder.EnableSensitiveDataLogging' 查看 键值冲突。 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap.Add(TKey 键,InternalEntityEntry 条目)
repo 被注册为 Transient like:
services.AddTransient<EntryRepository>();
我尝试在插入后使用 Detach,但使用它更新会清除所有未更新的字段。我不记得是什么导致了这个问题。
【问题讨论】:
-
类Entry是否仅在DB中的单个表中添加/更新或有多个表插入一条记录,原因可能是子条目之一被锁定。您必须在读取该实体时找到它并使用 Asnotracking(尽管这会有并发问题)。您可以使用 ChangeTracker.Entries() 来查找被跟踪的条目。要忽略其他字段的更新,您需要在每个属性中将 IsModified 设置为 false。像这样的东西 - this.Entry(entry).Property(x => x.Property1).IsModified = false;
-
@RaviA。我已经在使用 AsNoTracking 来读取实体,添加了代码。我看不出问题出在哪里
-
这个调用和数据库之间的某个地方我相信它仍然被跟踪。您是否尝试过我建议的方法来查找仍在跟踪的条目?大多数时候它是子条目之一。
-
我试过的是一个简单的对象映射一对一的表
标签: c# entity-framework-core asp.net-core-webapi