How to add a comment to owned JSON column in EF Core?

410 Views Asked by At

Given an EF Core entity with an owned type that's stored in a JSON column like so

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");
  }
}

The HasComment call will result in a failure when trying to create a migration using dotnet ef migrations add. The message given is

System.InvalidOperationException: 'Metadata' cannot be used as a property on entity type 'MyEntity' because it is configured as a navigation.

I understand that the reason for this is probably because if tomorrow I choose to store this Metadata in a separate table, then I can't have a "column comment" anymore. How can I go about overriding this and adding a comment?

The only thing I've come up with is editing the migration manually to add a comment, but this means that if we want to edit a comment later in the future, we'd have to manually edit it again, so I'd prefer to let EF Core generate the instruction for us.

1

There are 1 best solutions below

3
On

Metadata is not a column in a table, it is a navigation property, which should point to a record in another table that holds your desired info.

However, in your scenario, you don't really need a navigation property. You can just adjust your code so that the "JSON" column is a string.

public MyEntity(SomeMetadata metadata) : this()
{
    Metadata = metadata.SomeNestedThing;
}

public string Metadata { get; private set; }

After these changes, Metadata will be an actual column in the table and your code for adding the comment will work.