Search code examples
c#entity-framework-corediscriminatorowned-types

Configuration for EF core to store multiple collection properties of the same type (value objects) in the single table


Now I've realized that it is something hard to do for me.

Given:

EF Core 8

// мodels are simplified to highlight the essence

public class Notification
{
    public Guid Id { get; set; }
    public EmailAddress From { get; set; }
    
    public ICollection<EmailAddress> To { get; set; }
    public ICollection<EmailAddress> Cc { get; set; }
    public ICollection<EmailAddress> Bcc { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }
}

public class EmailAddress
{
    public string DisplayName { get; set; }
    public string Address { get; set; }
}

Need to get some configuration that the all email addressed will end up in the same table with some discriminator column maybe. Like

notification table

id from subject body

emailaddresses table

id notification_id to cc bcc discriminator

or more preferable

id notification_id address discriminator

Solution

  • You can use the table-per-hierarchy with a discriminator feature to do this.

    Extend EmailAddress to have a type per collection:

    public class ToEmailAddress : EmailAddress { }
    public class CcEmailAddress : EmailAddress { }
    public class BccEmailAddress : EmailAddress { }
    

    Modify Notification use the new types:

        public ICollection<ToEmailAddress> To { get; set; }
        public ICollection<CcEmailAddress > Cc { get; set; }
        public ICollection<BccEmailAddress> Bcc { get; set; }
    

    Update the model configuration for EmailAddress to register the new types and desired discriminators:

        modelBuilder.Entity<EmailAddress>()
            .HasDiscriminator<string>("discriminator")
            .HasValue<EmailAddress>("base")
            .HasValue<ToEmailAddress>("to")
            .HasValue<CcEmailAddress>("cc")
            .HasValue<BccEmailAddress>("bcc");