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

EF Core中附加实体后JSON列未更新的问题求助

问题描述

我的实体类定义如下:

public class UserSetting{    
    [Key]    
    public int UserSettingId { get; set; }    
    public string UserLanguage { get; set; }    
    public string HelpTourList { get; set; }    
    public CalenderTypeEnum UserCalender { get; set; }    
    public NumericFormatEnum NumericFormat { get; set; }    
    public List<AggridStates> AggridStates { get; set; }    
    public int FontSize { get; set; }    
    public virtual User User { get; set; }    
    public int? UserId { get; set; }
}

其中AggridStates被配置为JSON列:

builder.OwnsMany(author => author.AggridStates, c=> c.ToJson());

使用跟踪查询获取实体并更新AggridStates时,一切正常:

var obj = BaseService.GetAll().Where(c => c.UserId == null).FirstOrDefault();
obj.AggridStates = new List<AggridStates>() { input };
await context.SaveChangesAsync();

但使用无跟踪查询获取实体,附加到上下文后再更新时,JSON列AggridStates并未同步更新:

var obj = BaseService.GetAll().Where(c => c.UserId == null).FirstOrDefault();
obj.AggridStates = new List<AggridStates>() { input };
context.Attach(entity);
await context.SaveChangesAsync();

请问该如何解决这个问题?

解决方案
  • 附加后显式标记JSON属性为已修改
    无跟踪查询返回的实体被附加到上下文时,EF Core默认将其标记为Unchanged状态,无法自动检测到JSON类型Owned集合的变更。需要手动告知EF该属性已更新:

    var obj = BaseService.GetAll().AsNoTracking().Where(c => c.UserId == null).FirstOrDefault();
    obj.AggridStates = new List<AggridStates>() { input };
    context.Attach(obj);
    // 标记AggridStates属性为已修改
    context.Entry(obj).Property(x => x.AggridStates).IsModified = true;
    await context.SaveChangesAsync();
    
  • 直接将实体状态设置为Modified
    这种方式会把实体的所有属性标记为已修改,适合需要批量更新多个属性的场景,但生成的SQL语句会包含所有字段:

    var obj = BaseService.GetAll().AsNoTracking().Where(c => c.UserId == null).FirstOrDefault();
    obj.AggridStates = new List<AggridStates>() { input };
    context.Entry(obj).State = EntityState.Modified;
    await context.SaveChangesAsync();
    
  • 修改集合内容而非替换整个集合
    如果不需要替换整个集合,只是修改其中元素,可先附加实体,操作集合后再标记属性:

    var obj = BaseService.GetAll().AsNoTracking().Where(c => c.UserId == null).FirstOrDefault();
    context.Attach(obj);
    obj.AggridStates.Clear();
    obj.AggridStates.Add(input);
    context.Entry(obj).Property(x => x.AggridStates).IsModified = true;
    await context.SaveChangesAsync();
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 21:20:17