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

EF Core映射JSON列更新报错:Invalid column name 'MORE_DATA'

问题排查与解决方案

问题根源

你的更新逻辑中反射强制复制所有属性的操作,导致EF Core错误地将嵌套在JSON字段内的MORE_DATA识别为实体的顶级数据库列,而非JSON结构的一部分:

  1. 你通过AsNoTracking获取现有实体后,调用Attach让上下文开始追踪该实体。
  2. 反射遍历所有属性时,错误触发了EF Core的追踪逻辑,将MORE_DATA当成了需要映射到数据库表的独立列(而非嵌套JSON的子对象)。
  3. EF Core生成SQL时尝试引用不存在的MORE_DATA列,最终抛出Invalid column name 'MORE_DATA'错误。

解决方案

方案1:简化更新逻辑(推荐)

放弃手动反射复制属性的操作,直接使用EF Core内置的更新逻辑,它能正确识别JSON嵌套属性:

public virtual async Task<T> UpdateAsync(T entity, AuditDetail auditDetail)
{
    var id = entity?.ID;
    if (entity == null) throw new ArgumentNullException(nameof(entity));

    try
    {
        var existingEntity = await _dbContext.Set<T>().AsNoTracking().FirstOrDefaultAsync(a => a.ID == id);
        if (existingEntity == null) throw new EntityNotFoundException();

        // 保留创建信息
        entity.CreatedByID = existingEntity.CreatedByID;
        entity.CreationTS = existingEntity.CreationTS;

        // 直接更新传入的实体,EF自动处理JSON嵌套属性
        _dbContext.Set<T>().Update(entity);
        await _dbContext.SaveChangesAsync();

        return entity;
    }
    catch (Exception ex)
    {
        LogError("Update", id, ex);
        throw;
    }
}

方案2:修复反射复制逻辑

如果必须保留手动复制属性的逻辑,需要排除JSON嵌套相关属性,仅更新顶级非JSON属性:

public virtual async Task<T> UpdateAsync(T entity, AuditDetail auditDetail)
{
    var id = entity?.ID;
    if (entity == null) throw new ArgumentNullException(nameof(entity));

    try
    {
        var existingEntity = await _dbContext.Set<T>().AsNoTracking().FirstOrDefaultAsync(a => a.ID == id);
        if (existingEntity == null) throw new EntityNotFoundException();

        // 保留创建信息
        entity.CreatedByID = existingEntity.CreatedByID;
        entity.CreationTS = existingEntity.CreationTS;

        _dbContext.Attach(existingEntity);

        // 仅复制非JSON嵌套的顶级属性
        var propsToUpdate = entity.GetType().GetProperties()
            .Where(p => p.Name != nameof(TableEntity.json_field)); // 替换为你的JSON字段属性名

        foreach (var prop in propsToUpdate)
        {
            var existingProp = existingEntity.GetType().GetProperty(prop.Name);
            existingProp?.SetValue(existingEntity, prop.GetValue(entity));
        }

        // 单独处理JSON嵌套属性的更新
        if (entity.json_field != null)
        {
            existingEntity.json_field = entity.json_field;
        }

        _dbContext.Set<T>().Update(existingEntity);
        await _dbContext.SaveChangesAsync();

        return existingEntity;
    }
    catch (Exception ex)
    {
        LogError("Update", id, ex);
        throw;
    }
}

额外检查:实体类结构匹配

确保你的实体类结构与映射配置完全对应,示例结构如下:

public class TableEntity
{
    public int ID { get; set; }
    public string CreatedByID { get; set; }
    public DateTime CreationTS { get; set; }
    // 对应映射中的json_field
    public JsonFieldType json_field { get; set; }
}

public class JsonFieldType
{
    // 嵌套的JSON对象
    public MORE_DATA MORE_DATA { get; set; }
}

public class MORE_DATA
{
    // JSON字段内容
    public string SomeProperty { get; set; }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 12:58:08