将 ICollection<string> 映射到 EF Core 8 中的 JSON 列

问题描述 投票:0回答:1

我正在使用 EF Core 8 和 Postgres 适配器。

我需要这个实体属性作为 JSON:

public ICollection<string> Messages { get; } = [];

我尝试过这个配置:

builder.OwnsOne(x => x.Messages, x => x.ToJson());

这不起作用,因为它已将

"{ Capacity: 4 }"
保存在数据库中。

我尝试过这个配置:

builder.Property(x => x.Messages).HasColumnType("jsonb");

这会引发

NotSupportedException

我尝试了各种其他组合和解决方法。

多年来,尽管 JSON 映射已得到改进,但始终存在错误或缺点。

我知道 .NET 9 昨天发布了,可能对基元和字符串集合进行了一些改进,但我们现在无法升级。

.NET 8 中有哪些功能?

c# .net entity-framework-core ef-core-8.0
1个回答
0
投票

我在值转换器的文档中找到了答案。尽管没有使用

HasColumnType("jsonb")
ToJson()
,它还是序列化为 json。

modelBuilder
  .Entity<Customer>()
  .Property(x => x.Messages)
  //.HasColumnType("jsonb")      // unnecessary
  .HasConversion(
    c => JsonSerializer.Serialize(c, JsonSerializerOptions.Default),
    s => JsonSerializer.Deserialize<ICollection<string>>(s, JsonSerializerOptions.Default)!,
    new ValueComparer<ICollection<string>>(
      (c1, c2) => c1!.SequenceEqual(c2!),
      c => c.Aggregate(0, (acc, val) => HashCode.Combine(acc, val.GetHashCode(StringComparison.Ordinal))),
      c => new Collection<string>(c.ToList()))
  );

示例:

customer.Messages.Add("foo");
customer.Messages.Add("bar");
customer.Messages.Add("baz");

数据库记录将有:

["foo","bar","baz"]
© www.soinside.com 2019 - 2024. All rights reserved.