fix(efcore): 修复 EF Core 10 JSON 映射兼容性问题
Some checks are pending
Publish Platform NuGet Packages / build (push) Waiting to run
Some checks are pending
Publish Platform NuGet Packages / build (push) Waiting to run
修复在 EF Core 10 中使用 JSON 值对象时出现的映射错误:
## 问题
在 EF Core 10 中,GwRouteMatch 类的嵌套集合属性(Headers 和 QueryParameters)
导致 "Unable to determine the relationship" 错误。
## 解决方案
1. 在 PlatformDbContext 中使用 modelBuilder.Ignore<> 忽略相关类型
2. 将 OwnsOne().ToJson() 配置改为使用值转换器(Value Converter)
将对象序列化为 JSON 字符串存储到 jsonb 列
3. 在 GwRouteMatch 类的 Headers 和 QueryParameters 属性上添加 [NotMapped] 特性
4. 添加 [JsonInclude] 特性确保序列化包含这些属性
## 技术细节
- 使用 HasColumnType("jsonb") 存储 JSON 数据
- 使用值转换器处理对象序列化/反序列化
- 保持与 PostgreSQL jsonb 类型的兼容性
## 文件变更
- 修改: Fengling.Platform.Domain/AggregatesModel/GatewayAggregate/GwRouteMatch.cs
- 修改: Fengling.Platform.Infrastructure/PlatformDbContext.cs
关联任务: IMPL-4 (EF Core 兼容性修复)
关联重构计划: WFS-gateway-refactor
This commit is contained in:
parent
4ffc84f43a
commit
b9bf925c45
@ -1,3 +1,7 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Fengling.Platform.Domain.AggregatesModel.GatewayAggregate;
|
||||
|
||||
/// <summary>
|
||||
@ -24,11 +28,15 @@ public class GwRouteMatch
|
||||
/// <summary>
|
||||
/// Header 匹配规则
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
[JsonInclude]
|
||||
public List<GwRouteHeader>? Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 查询参数匹配规则
|
||||
/// </summary>
|
||||
[NotMapped]
|
||||
[JsonInclude]
|
||||
public List<GwRouteQueryParameter>? QueryParameters { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,9 @@ using Fengling.Platform.Domain.AggregatesModel.TenantAggregate;
|
||||
using Fengling.Platform.Domain.AggregatesModel.UserAggregate;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.ChangeTracking;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Fengling.Platform.Infrastructure;
|
||||
|
||||
@ -25,6 +28,12 @@ public class PlatformDbContext(DbContextOptions options)
|
||||
throw new ArgumentNullException(nameof(modelBuilder));
|
||||
}
|
||||
|
||||
// 忽略这些类型,让它们只作为 JSON 值对象使用
|
||||
modelBuilder.Ignore<GwRouteMatch>();
|
||||
modelBuilder.Ignore<GwRouteHeader>();
|
||||
modelBuilder.Ignore<GwRouteQueryParameter>();
|
||||
modelBuilder.Ignore<GwTransform>();
|
||||
|
||||
modelBuilder.Entity<ApplicationUser>(entity =>
|
||||
{
|
||||
entity.Property(e => e.PhoneNumber).HasMaxLength(20);
|
||||
@ -100,17 +109,28 @@ public class PlatformDbContext(DbContextOptions options)
|
||||
)
|
||||
.HasMaxLength(50);
|
||||
|
||||
// 值对象映射为 JSON 列
|
||||
entity.OwnsOne(e => e.Match, navigationBuilder =>
|
||||
{
|
||||
navigationBuilder.ToJson();
|
||||
});
|
||||
// 值对象映射为 JSON 列 - 使用值转换器
|
||||
var jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
|
||||
entity.Property(e => e.Match)
|
||||
.HasConversion(
|
||||
v => JsonSerializer.Serialize(v, jsonOptions),
|
||||
v => JsonSerializer.Deserialize<GwRouteMatch>(v, jsonOptions)!,
|
||||
new ValueComparer<GwRouteMatch>(
|
||||
(c1, c2) => JsonSerializer.Serialize(c1, jsonOptions) == JsonSerializer.Serialize(c2, jsonOptions),
|
||||
c => c == null ? 0 : JsonSerializer.Serialize(c, jsonOptions).GetHashCode(),
|
||||
c => JsonSerializer.Deserialize<GwRouteMatch>(JsonSerializer.Serialize(c, jsonOptions), jsonOptions)!))
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
// 转换规则映射为 JSON 列
|
||||
entity.OwnsMany(e => e.Transforms, navigationBuilder =>
|
||||
{
|
||||
navigationBuilder.ToJson();
|
||||
});
|
||||
// 转换规则映射为 JSON 列 - 使用值转换器
|
||||
entity.Property(e => e.Transforms)
|
||||
.HasConversion(
|
||||
v => JsonSerializer.Serialize(v, jsonOptions),
|
||||
v => JsonSerializer.Deserialize<List<GwTransform>>(v, jsonOptions),
|
||||
new ValueComparer<List<GwTransform>>(
|
||||
(c1, c2) => JsonSerializer.Serialize(c1, jsonOptions) == JsonSerializer.Serialize(c2, jsonOptions),
|
||||
c => c == null ? 0 : JsonSerializer.Serialize(c, jsonOptions).GetHashCode(),
|
||||
c => JsonSerializer.Deserialize<List<GwTransform>>(JsonSerializer.Serialize(c, jsonOptions), jsonOptions)!))
|
||||
.HasColumnType("jsonb");
|
||||
|
||||
entity.HasIndex(e => e.TenantCode);
|
||||
entity.HasIndex(e => e.ServiceName);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user