使用 IEntityTypeConfiguration 在 EF 中配置字符串列表的 JSON 列

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

我对实体框架的 JSON 列支持感到很兴奋。但是,我在配置我的实体以使用它时遇到问题。这是我的实体,为清楚起见进行了简化:

public class Bill : EntityBase
{
    public DateTimeOffset BillDate { get; set; } = DateTimeOffset.Now;

    public DateTimeOffset? DeliveryDate { get; set; }

    public IList<string> OrderNumbers { get; set; } = new List<string>();

    public IList<string> CustomerOrderNumbers { get; set; } = new List<string>();

我使用

IEntityTypeConfiguration<T>
来配置我的实体,因为我发现我在如何设置表方面获得了很多粒度。这是相应的配置:

public class BillConfiguration : IEntityTypeConfiguration<Bill>
    {
        public void Configure(EntityTypeBuilder<Bill> builder)
        {
            // Primary Key
            builder.HasKey(x => x.Id);
            builder.Property(x => x.Id)
                .HasColumnOrder(0);

            // (snipping audit and version columns)

            // Property settings
            builder.Property(x => x.BillDate)
                .HasColumnOrder(6);

            builder.Property(x => x.DeliveryDate)
                .HasColumnOrder(7);

            builder.Property(x => x.OrderNumbers)
                .HasColumnOrder(8);

            builder.Property(x => x.CustomerOrderNumbers)
                .HasColumnOrder(9);

但是,在创建初始迁移时,它会抛出以下错误:

The property 'Bill.CustomerOrderNumbers' could not be mapped because it is of type 'IList<string>', which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

这个错误是有道理的,但我不确定“支持”来自哪里。我做了一个转换器:

public class StringListValueConverter : ValueConverter<IList<string>, string>
    {
        public StringListValueConverter()
            : base(
                value => JsonSerializer.Serialize(value, JsonSerializerOptions.Default),
                dbValue => JsonSerializer.Deserialize<IList<string>>(dbValue, JsonSerializerOptions.Default) ?? new List<string>()
            )
        {
        }
    }

然后我可以根据

这篇博文
在列上使用.HasConversion<StringListValueConverter>()

我不明白 EF 的新“功能”在哪里。我不能一直这样做吗?有没有更简单的方法来做到这一点而不需要手动转换?

c# sql-server entity-framework entity-framework-core
2个回答
0
投票

我相信您可能错过了转换电话。这是 .NET 6 中的一个示例;请放心使用。

上下文文件:

  // builder
  model.Entity<Bill>()
    .Property(t => t. OrderNumbers)
    .HasColumnType("nvarchar(max)")
    .HasJsonConversion();

扩展方法:

  public static PropertyBuilder<T> HasJsonConversion<T>(this PropertyBuilder<T> propertyBuilder)
  {
    var converter = new ValueConverter<T, string>(
      v => JSerialize(v),
      v => JDeserialize<T>(v));

    var comparer = new ValueComparer<T>(
      (l, r) => JSerialize(l) == JSerialize(r),
      v => v == null ? 0 : JSerialize(v).GetHashCode(),
      v => JDeserialize<T>(JSerialize(v)));

    propertyBuilder.HasConversion(converter);
    propertyBuilder.Metadata.SetValueConverter(converter);
    propertyBuilder.Metadata.SetValueComparer(comparer);

    return propertyBuilder;
  }

注意:更改 json 转换器。


0
投票

我不明白 EF 的新“功能”在哪里

这是可以理解的,因为此时官方文档尚未更新,并且“新功能”仅在 EF Core 7 的“新增功能”部分中解释 - JSON Columns

该功能应该仅针对拥有的实体类型(OwnsOne

 / 
OwnsMany
)使用相应构建器的
ToJson()
流利API激活。

但是,文档说

注意

尚不支持将原始类型集合映射到 JSON。上面的文档使用值转换器将集合转换为逗号分隔的字符串。投票给

Json:添加对原始类型集合的支持(如果您对此感兴趣)。

这仅仅意味着您不能将它用于您的

string

 列表,而应该求助于旧的超值转换器。至少在 EF7 中是这样。根据链接的 GitHub 问题,它已在即将推出的 EF8 中实现。怎么办 - 我现在不知道,EF8 还没有发布,我有一个强烈的政策,不尝试/测试预览软件。

© www.soinside.com 2019 - 2024. All rights reserved.