You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core非全量加载实体更新部分列时抛出DbUpdateConcurrencyException

问题分析与解决方案

首先直接给结论:你这种投影到新LearningDocument实例的方式本身是可行的,但你遗漏了关键的并发令牌列VersionStamp,这正是导致DbUpdateConcurrencyException的原因。

为什么会抛出并发异常?

你的实体类里有VersionStamp(timestamp类型),EF Core会自动把这种类型的列识别为并发令牌——在更新时,EF会用这个值来验证数据是否被其他进程修改过。但你在投影的时候只选择了LearningDocumentId、IsDone和ModifiedDateTime,没有包含VersionStamp。当你Attach这个新实例并执行更新时:

  • EF生成的UPDATE语句会尝试匹配LearningDocumentId,但同时会检查VersionStamp是否与数据库中的值一致;
  • 由于你的实例里VersionStamp是默认值(空byte数组),和数据库中实际的时间戳不匹配,导致数据库中没有符合条件的行被更新,于是抛出“预期影响1行,实际影响0行”的异常。

修复方案

方案1:在投影中包含并发令牌列

只需要修改Select部分,把VersionStamp也包含进来,这样EF就能正确进行并发检查,定位到要更新的行:

var dbContext = GetDBContext();
var documents = await dbContext.LearningDocuments
    .Where(x => x.LearningRequestID == 1234)
    .Select(x => new LearningDocument() {
        LearningDocumentId = x.LearningDocumentId,
        IsDone = x.IsDone,
        ModifiedDateTime = x.ModifiedDateTime,
        VersionStamp = x.VersionStamp // 新增:带上并发令牌列
    })
    .ToListAsync()
    .ConfigureAwait(false);

documents.ForEach(d => {
    d.IsDone = true;
    d.ModifiedDateTime = DateTime.UtcNow;
    dbContext.LearningDocuments.Attach(d);
    dbContext.Entry(d).Property(x => x.IsDone).IsModified = true;
    dbContext.Entry(d).Property(x => x.ModifiedDateTime).IsModified = true;
});

await dbContext.SaveChangesAsync().ConfigureAwait(false);

方案2:使用EF Core的ExecuteUpdate(推荐,EF Core 7+支持)

如果你只是要批量更新特定列,完全不需要把实体加载到内存——EF Core 7及以上版本提供的ExecuteUpdate可以直接在数据库层面执行批量更新,性能更高,代码也更简洁:

var dbContext = GetDBContext();
await dbContext.LearningDocuments
    .Where(x => x.LearningRequestID == 1234)
    .ExecuteUpdateAsync(s => s
        .SetProperty(x => x.IsDone, true)
        .SetProperty(x => x.ModifiedDateTime, DateTime.UtcNow))
    .ConfigureAwait(false);

这种方式不会加载任何实体到内存,直接生成并执行UPDATE SQL语句,同时如果需要并发检查,也可以在Where条件中加入VersionStamp的判断(比如匹配特定版本)。

总结

投影到新实体实例来更新部分列是可行的,但必须确保包含主键和并发令牌(如果有的话)这两类关键属性,否则EF无法正确定位和验证数据库中的行。而对于批量更新场景,ExecuteUpdate是更优的选择,既满足你“不完整加载实体到内存”的需求,又能提升性能。

内容的提问来源于stack exchange,提问作者LP13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:32:08