EF Core でエンティティ フィールドに JSON を保存するにはどうすればよいでしょうか? 質問する

EF Core でエンティティ フィールドに JSON を保存するにはどうすればよいでしょうか? 質問する

私は .NET Core (.NETStandard 1.4 をターゲット) を使用して再利用可能なライブラリを作成しており、Entity Framework Core を使用しています (どちらも初めてです)。次のようなエンティティ クラスがあります。

public class Campaign
{
    [Key]
    public Guid Id { get; set; }

    [Required]
    [MaxLength(50)]
    public string Name { get; set; }

    public JObject ExtendedData { get; set; }
}

DbSet を定義する DbContext クラスがあります。

public DbSet<Campaign> Campaigns { get; set; }

(DI でリポジトリ パターンも使用していますが、これは関係ないと思います。)

ユニットテストで次のエラーが発生します:

System.InvalidOperationException: タイプ 'JContainer' のナビゲーション プロパティ 'JToken.Parent' によって表されるリレーションシップを判別できません。リレーションシップを手動で構成するか、モデルからこのプロパティを無視してください。

これは関係ではなく、大きな文字列として保存する必要があることを示す方法はありますか?

ベストアンサー1

これについては別の答えをします。

理想的には、ドメイン モデルはデータがどのように保存されるかを認識しない必要があります。バッキング フィールドと追加の[NotMapped]プロパティを追加すると、実際にはドメイン モデルがインフラストラクチャに結合されます。

覚えておいてください - 重要なのはドメインであり、データベースではありません。データベースはドメインの一部を保存するために使用されているだけです。

代わりに、オブジェクトに対して EF Core のHasConversion()メソッドを使用してEntityTypeBuilder、型と JSON 間の変換を行うことができます。

次の 2 つのドメイン モデルがあるとします。

public class Person
{
    public int Id { get; set; }

    [Required]
    [MaxLength(50)]
    public string FirstName { get; set; }

    [Required]
    [MaxLength(50)]
    public string LastName { get; set; }

    [Required]
    public DateTime DateOfBirth { get; set; }

    public IList<Address> Addresses { get; set; }      
}

public class Address
{
    public string Type { get; set; }
    public string Company { get; set; }
    public string Number { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
}

ドメインが関心を持つ属性のみを追加しました。DB が関心を持つ詳細は追加していません。つまり、ありません[Key]

私の DbContextIEntityTypeConfigurationには次のものがありますPerson:

public class PersonsConfiguration : IEntityTypeConfiguration<Person>
{
    public void Configure(EntityTypeBuilder<Person> builder)
    {
        // This Converter will perform the conversion to and from Json to the desired type
        builder.Property(e => e.Addresses).HasConversion(
            v => JsonConvert.SerializeObject(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }),
            v => JsonConvert.DeserializeObject<IList<Address>>(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }));
    }
}

この方法を使えば完全にドメインをインフラストラクチャから切り離します。すべてのバッキング フィールドと追加のプロパティは必要ありません。

おすすめ記事