给定一个 EF Core 实体,其拥有的类型存储在 JSON 列中,就像这样
public class MyEntity
{
public MyEntity( SomeMetadata metadata) : this()
{
Metadata = metadata;
}
/// <summary>
/// Just for EntityFramework because it can't handle a constructor with owned type.
/// </summary>
private MyEntity()
{
}
public Guid PrimaryId { get; private set; }
public SomeMetadata Metadata { get; private set; }
public class SomeMetadata
{
public string? SomeNestedThing { get; set; }
}
}
public class MyEntityConfiguration : IEntityTypeConfiguration<MyEntity>
{
public void Configure(EntityTypeBuilder<MyEntity> builder)
{
builder.OwnsOne(e => e.Metadata, ownedNavigationBuilder =>
{
ownedNavigationBuilder.ToJson();
});
builder.Property(e => e.Metadata)
.HasComment("Comment about this JSON column");
}
}
尝试使用
HasComment
创建迁移时,dotnet ef migrations add
调用将导致失败。给出的信息是
System.InvalidOperationException:“元数据”不能用作实体类型“MyEntity”的属性,因为它被配置为导航。
我理解,之所以这样,大概是因为如果明天我选择把这个
Metadata
存到一个单独的表中,那我就不能再有“列评论”了。我怎样才能覆盖它并添加评论?
我唯一想到的是手动编辑迁移以添加评论,但这意味着如果我们以后想编辑评论,我们必须再次手动编辑它,所以我会更愿意让 EF Core 为我们生成指令。
Metadata
不是表中的一列,它是一个导航属性,它应该指向另一个表中包含您所需信息的记录。
但是,在您的场景中,您实际上并不需要导航属性。你可以调整你的代码,使“JSON”列是一个字符串。
public MyEntity(SomeMetadata metadata) : this()
{
Metadata = metadata.SomeNestedThing;
}
public string Metadata { get; private set; }
解决此问题的一种方法是为拥有的类型创建一个单独的配置,并改为在该配置中设置属性的注释。
这是一个如何向 JSON 列添加注释的示例:
public class MyEntityConfiguration : IEntityTypeConfiguration<MyEntity>
{
public void Configure(EntityTypeBuilder<MyEntity> builder)
{
builder.OwnsOne(e => e.Metadata, metadataBuilder =>
{
metadataBuilder.Property(p => p.SomeNestedThing).HasComment("Comment about this JSON column");
metadataBuilder.ToJson();
});
}
}
我们将 SomeMetadata 类型与 MyEntity 类型分开配置。我们在 SomeMetadata 类型的 SomeNestedThing 属性上设置注释,这应该有效,因为此属性未配置为导航属性。