在 EF Core 中具有自动序列化/反序列化的自定义类型

lme*_*213 7 c# asp.net entity-framework entity-framework-core asp.net-core

我正在使用该ical.net库来处理我的 ASP.NET Core 2 应用程序中的重复规则和重复事件。我希望能够序列化一个CalendarEvent对象并将其保存在数据库中,我正在寻找这样做的最佳实践方法。我考虑过使用非映射属性来保存实际对象,并定义字符串映射属性,并使用 中的事件处理程序DbContext来序列化对象并将其设置为字符串 prop,然后再保存实体,同样重新创建CalendarEvent构建实体时序列化字符串中的对象。类似于以下内容:

public class AvailabilityRule: ApplicationEntity
{
    ...

    [NotMapped]
    public CalendarEvent Event { get; set; }

}

public class ApplicationDbContext : AuditableDbContext
{
    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<AvailabilityRule>().Property<string>("SerializedEvent");
    }

    public override int SaveChanges()
    {
        // Get instances of AvailabilityRule from ChangeTracker, and
        // set the serialized property
    }
}
Run Code Online (Sandbox Code Playgroud)

我假设有一个类似的方法我可以重写以在从数据库中提取记录时执行相反的操作,但我不知道它是什么。

作为新的ASP.NET和Entity Framework,我关心的是做事的正确方法TM,所以我很有兴趣知道我是否有更好的方法。我在网上找不到关于这个主题的太多信息。

Men*_*tor 9

使用EF Core 2.1 中添加的值转换,将复杂实体作为 JSON 存储在单个数据库列中变得非常容易。

[NotMapped] 不需要

public class AvailabilityRule: ApplicationEntity
{
   ...
    // [NotMapped]
    public CalendarEvent Event { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

为 PropertyBuilder 添加以下扩展:

public static class PropertyBuilderExtensions
{
    public static PropertyBuilder<T> HasJsonConversion<T>(this PropertyBuilder<T> propertyBuilder) where T : class, new()
    {
        ValueConverter<T, string> converter = new ValueConverter<T, string>
        (
            v => JsonSerializer.Serialize(v, null),
            v => JsonSerializer.Deserialize<T>(v, null) ?? new T()
        );

        ValueComparer<T> comparer = new ValueComparer<T>
        (
            (l, r) => JsonSerializer.Serialize(l, null) == JsonSerializer.Serialize(r, null),
            v => v == null ? 0 : JsonSerializer.Serialize(v, null).GetHashCode(),
            v => JsonSerializer.Deserialize<T>(JsonSerializer.Serialize(v, null), null)
        );

        propertyBuilder.HasConversion(converter);
        propertyBuilder.Metadata.SetValueConverter(converter);
        propertyBuilder.Metadata.SetValueComparer(comparer);
        propertyBuilder.HasColumnType("jsonb");

        return propertyBuilder;
    }
}
Run Code Online (Sandbox Code Playgroud)

在数据库上下文的 OnModelCreating 方法中需要调用 HasJsonConversion,它对您的对象进行序列化、反序列化和跟踪更改

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);
    modelBuilder.Entity<AvailabilityRule>()
        .Property(b => b.Event )
        .HasJsonConversion();
}
Run Code Online (Sandbox Code Playgroud)