迁移EDMX模型后EF序列化出现$id与EntityKey字段异常问题
解决EDMX迁移后WebAPI返回$id和EntityKey的问题
看起来你遇到的核心问题是实体序列化时带上了EF框架的内部属性($id和EntityKey),导致回传时$id被误当作业务ID。结合你的描述,我整理了几个针对性的解决方案,按优先级排序:
1. 确保WebAPI的Json序列化配置完全迁移
旧项目里的WebAPI配置是关键,你需要把这些配置完整复制到新项目的WebApiConfig.cs中,尤其是序列化相关的设置:
using System.Net.Http.Formatting; using System.Net.Http.Headers; using Newtonsoft.Json; public static class WebApiConfig { public static void Register(HttpConfiguration config) { // 保留旧项目的text/html媒体类型支持 config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); var jsonFormatter = config.Formatters.JsonFormatter; // 关闭引用保留,避免生成$id字段 jsonFormatter.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.None; // 处理循环引用(如果有的话) jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; // 可选:设置缩进,方便调试 jsonFormatter.SerializerSettings.Formatting = Formatting.Indented; // 保留你旧项目的WrappingHandler config.MessageHandlers.Add(new WrappingHandler()); // 可选:移除XML格式化器,确保默认返回Json config.Formatters.Remove(config.Formatters.XmlFormatter); } }
这里的核心是PreserveReferencesHandling.None,它会告诉Newtonsoft.Json不要生成用于跟踪对象引用的$id字段。
2. 关闭EF的代理创建(或调整实体生成策略)
如果上面的配置还没解决问题,可能是EF生成了动态代理类,这类代理会包含EntityKey等内部属性。你可以在上下文的构造函数中关闭代理创建:
public class YourDbContext : DbContext { public YourDbContext() : base("YourConnectionString") { // 关闭动态代理生成 this.Configuration.ProxyCreationEnabled = false; // 可选:关闭延迟加载,如果不需要的话 this.Configuration.LazyLoadingEnabled = false; } // DbSet定义... }
关闭代理后,EF会返回纯实体类,不会附带EntityKey等框架属性。
如果你的旧项目用的是POCO实体(而非默认的EntityObject),那还要检查新项目EDMX的代码生成策略:
- 打开EDMX设计器,右键空白处→属性
- 找到代码生成策略,确保和旧项目一致(比如设置为“无”,然后使用POCO T4模板生成实体)
默认的“EF 6.x DbContext Generator”生成的实体是POCO,不会包含EntityKey属性,而旧的“EntityObject Generator”会生成带EntityKey的实体,这可能是问题所在。
3. 全局忽略EntityKey属性(如果必须保留代理)
如果你需要保留EF代理(比如要用到延迟加载),可以通过自定义契约解析器全局忽略EntityKey属性,不用逐个修改实体:
using Newtonsoft.Json.Serialization; using System.Collections.Generic; using System.Reflection; public class IgnoreEntityKeyResolver : DefaultContractResolver { protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) { var properties = base.CreateProperties(type, memberSerialization); // 过滤掉所有名为EntityKey的属性 return properties.Where(p => p.PropertyName != "EntityKey").ToList(); } }
然后在WebApiConfig中注册这个解析器:
jsonFormatter.SerializerSettings.ContractResolver = new IgnoreEntityKeyResolver();
4. 验证NuGet包的一致性
虽然你说版本一致,但还是建议:
- 清理新项目的NuGet缓存:右键解决方案→管理NuGet程序包→设置→清除所有NuGet缓存
- 重新安装所有相关包,确保没有版本冲突:
Update-Package -Reinstall EntityFramework Update-Package -Reinstall Newtonsoft.Json Update-Package -Reinstall Microsoft.AspNet.WebApi.Core
这些步骤应该能解决你遇到的$id和EntityKey问题,优先尝试前两步,因为这是旧项目正常工作的核心配置。
内容的提问来源于stack exchange,提问作者Shir
相关产品推荐
相关产品推荐

