EF Core映射JSON列更新报错:Invalid column name 'MORE_DATA'
问题排查与解决方案
问题根源
你的更新逻辑中反射强制复制所有属性的操作,导致EF Core错误地将嵌套在JSON字段内的MORE_DATA识别为实体的顶级数据库列,而非JSON结构的一部分:
- 你通过
AsNoTracking获取现有实体后,调用Attach让上下文开始追踪该实体。 - 反射遍历所有属性时,错误触发了EF Core的追踪逻辑,将
MORE_DATA当成了需要映射到数据库表的独立列(而非嵌套JSON的子对象)。 - 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
相关产品推荐
相关产品推荐

