【问题标题】:EF Core - Insert then update an entryEF Core - 插入然后更新条目
【发布时间】: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


【解决方案1】:

通过先阅读条目,然后更新它来解决我在 repo 中的更新策略:

public async Task<Entry> UpdateEntryAsync(Entry updateEntry)
{
    DALENTRY entry = await _ctx.Set<DALENTRY >().SingleOrDefaultAsync(a => a.ID == updateEntry.IdEntry);

    entry.FIELD= updateEntry.IdField,

    _ctx.Update(entry);
    await _ctx.SaveChangesAsync();

    return updateEntry;
}

【讨论】:

  • 出于好奇,您是否应该将 AsNoTracking 添加到这一行 DALENTRY entry = await _ctx.Set().SingleOrDefaultAsync(a => a.ID == updateEntry.IdEntry);还是 Update 负责发布更改跟踪?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 2020-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多