.NET 7 Json多态序列化与EF Core 7 Json列兼容问题求助
解决EF Core 7中JSON列的多态序列化问题
核心问题分析
你遇到的问题本质是:
- EF Core 默认的
OwnsOne + ToJson()配置未启用多态序列化支持,导致派生类实例被序列化为空对象 - 手动用
HasConversion序列化会丢失EF Core对JSON结构的解析能力,无法支持服务器端查询
解决方案:配置EF Core使用带多态支持的JSON序列化选项
要同时实现多态序列化和服务器端JSON查询,需要让EF Core的JSON列功能使用尊重类上多态特性的序列化选项,步骤如下:
1. 确保实体类的多态特性配置正确
你的实体类配置已经正确,无需修改:
[JsonPolymorphic] [JsonDerivedType(typeof(FileMessageData), typeDiscriminator: nameof(FileMessageData))] public class MessageData { public string InCommon { get; set; } } [JsonDerivedType(typeof(FileMessageData), typeDiscriminator: nameof(FileMessageData))] public class FileMessageData : MessageData { public string FileName { get; set; } }
2. 在EF Core配置中指定多态序列化选项
有两种方式配置:全局配置或单个实体配置
方式一:全局配置(所有JSON列生效)
在DbContext的服务注册或配置中,指定使用JsonSerializerDefaults.General(该选项会自动识别类上的多态特性):
// 在AddDbContext时配置 services.AddDbContext<YourDbContext>(options => options.UseSqlServer("你的连接字符串", b => b.UseJsonSerializerOptions(new JsonSerializerOptions(JsonSerializerDefaults.General))));
方式二:单个实体配置(仅当前JSON列生效)
在实体的Fluent API配置中,给ToJson()指定序列化选项,并配置多态类型的ValueComparer:
using Microsoft.EntityFrameworkCore.Metadata.Internal; protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<MessageEntity>(builder => { builder.OwnsOne(e => e.Data, ownedNavigationBuilder => { // 启用JSON列 ownedNavigationBuilder.ToJson(); // 指定带多态支持的序列化选项 ownedNavigationBuilder.Property(x => x) .Metadata.SetAnnotation( CoreAnnotationNames.JsonSerializerOptions, new JsonSerializerOptions(JsonSerializerDefaults.General)); // 配置多态类型的ValueComparer,确保EF Core正确比较实例 ownedNavigationBuilder.Property(x => x) .Metadata.SetValueComparer(ValueComparer.CreateDefault(typeof(MessageData), true)); }); }); }
3. 验证效果
完成配置后:
- 保存
FileMessageData实例到MessageEntity.Data时,数据库中会生成包含类型鉴别器的JSON:{ "$type": "FileMessageData", "inCommon": "test", "fileName": "hellokitty.png" } - 服务器端查询如
DbSet<MessageEntity>().Where(m => m.Data.InCommon == "HoHo")会被EF Core正确翻译为SQL的JSON路径查询,无需客户端评估
为什么之前的方案失效?
- 直接
OwnsOne + ToJson():EF Core默认使用的序列化选项未启用多态支持,无法识别[JsonPolymorphic]特性,导致派生类实例被错误序列化 HasConversion手动序列化:EF Core将整个属性视为字符串,无法解析JSON内部结构,因此无法将LINQ查询翻译为SQL的JSON操作
内容的提问来源于stack exchange,提问作者martinoss
相关产品推荐
相关产品推荐

