using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using System; namespace DataLayer.Configurations { internal class BookConfig : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder entity) { entity.HasKey(b => b.BookId); entity.HasIndex(b => b.AudibleProductId); entity.OwnsOne(b => b.Rating); // // CRUCIAL: ignore unmapped collections, even get-only // entity.Ignore(nameof(Book.Authors)); entity.Ignore(nameof(Book.Narrators)); entity.Ignore(nameof(Book.TitleWithSubtitle)); entity.Ignore(b => b.Categories); // OwnsMany: "Can only ever appear on navigation properties of other entity types. // Are automatically loaded, and can only be tracked by a DbContext alongside their owner." entity .OwnsMany(b => b.Supplements, b_s => { b_s.WithOwner(s => s.Book) .HasForeignKey(s => s.BookId); b_s.HasKey(s => s.SupplementId); }); // even though it's owned, we need to map its backing field entity .Metadata .FindNavigation(nameof(Book.Supplements)) .SetPropertyAccessMode(PropertyAccessMode.Field); // owns it 1:1, store in separate table entity .OwnsOne(b => b.UserDefinedItem, b_udi => { b_udi.WithOwner(udi => udi.Book) .HasForeignKey(udi => udi.BookId); b_udi.Property(udi => udi.BookId).ValueGeneratedNever(); b_udi.ToTable(nameof(Book.UserDefinedItem)); b_udi.Property(udi => udi.LastDownloaded); b_udi .Property(udi => udi.LastDownloadedVersion) .HasConversion(ver => ver.ToString(), str => Version.Parse(str)); b_udi .Property(udi => udi.LastDownloadedFormat) .HasConversion(af => af.Serialize(), str => AudioFormat.Deserialize(str)); b_udi.Property(udi => udi.LastDownloadedFileVersion); // owns it 1:1, store in same table b_udi.OwnsOne(udi => udi.Rating); }); } } }