0

My app has an abstract base/parent class (Contact), and concrete child classes (Phone, Email) inheriting from the base, and other classes referenced from the base - I left Person and Notes for the sake of the question.

public class Phone : Contact
{
    public ConnectionType Type { get; set; } //public enum ConnectionType { Landline, Mobile, Fax, }
    //phone-specific fields
}

public class Email : Contact
{
    //email-specific fields
}

public abstract class Contact
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    //possibly something like public string Type { get; private set; } to be set with this.GetType().Name or enum based on similar logic

    public string Value { get; set; }

    // shared properties
    public UsageType Type { get; set; } //public enum UsageType { Personal, Business, Other, }

    public int PersonId { get; set; }
    
    [ForeignKey(nameof(PersonId))]
    public Person Person { get; set; }
    
    public List<Note> Notes { get; set; }
    
    // ... other shared properties
}

public class Note
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int ContactId { get; set; }

    public string Header { get; set; }
    public string Content { get; set; }

    [ForeignKey(nameof(ContactId))]
    public Contact Contact { get; set; }
}

This mimics domain logic.

Can I make EF Core create these tables:

  • Contacts
  • Phones (1-to-1 with Contact)
  • Emails (1-to-1 with Contact)
  • Persons (1-to-many with Contact)
  • Notes (many-to-1 with Contact)

without breaking parent-child relationship and with having same Id in parent and child?

I understand I can create database 1-to-1 parent-child relationship like

public class Phone
{
    [Key]
    public int Id { get; set; }

    public int ContactId { get; set; }

    [ForeignKey(nameof(ContactId))]
    public Contact Contact { get; set; }
}

public class Email
{
    [Key]
    public int Id { get; set; }

    public int ContactId { get; set; }

    [ForeignKey(nameof(ContactId))]
    public Contact Contact { get; set; }
}

public class Contact
{
    [Key]
    public int Id { get; set; }
}

which ultimately is going to provide my app with the same data, but I have an existing app which uses a NoSQL Db as a storage and I am changing the app to use a SQL database backed by EF Core and didn't want to make changes to the code much until it is absolutely necessary, plus currently our API allows to attach notes to any contact by contact Id and this is not possible to change as we cannot demand from users to change their API calls.

Edit: seems to be a duplicate of

Entity Framework : Table per Concrete Type and unique IDs across tables

which I didn't find when I was researching, sorry.

Funny enough, they even have almost same names in one of the answers!

5
  • 2
    EF supports 3 types of inheritance, though the two most common are TPH (table-per-herarchy) where all subclasses are stored in a single table with a discriminator (contact type) or TPC (table-per-concrete) where each sub-class is stored in a separate table, which is what it sounds like you are looking for. Everything is outlined here: learn.microsoft.com/en-us/ef/core/modeling/inheritance Commented Jan 7, 2024 at 21:15
  • I considered the idea of making it as a single table, but wrote it off as it would be a mix of entity-specific columns for tables with more properties. Table per concrete seems to be not the answer to my problem as I would need to check all tables to find a contact by Id - or create a separate table where I will be having the list of all contacts with ids and types. Now I reconsidered and probably will go that way as I looked into the resulted table and it is not that many columns in there - thanks for suggesting this. Also, thanks for the link - I saw it already, but didn't realize it is all. Commented Jan 7, 2024 at 21:33
  • @StevePy So, I will also consider Table-per-type configuration, but either TPH or TPT should serve my problem, thanks again! Commented Jan 7, 2024 at 21:52
  • 1
    You don't need a Contact table, you could make your Note table a TPH, with a discriminator and separate foreign key columns to each parent type.... Either design will work though. Commented Jan 8, 2024 at 0:01
  • @JeremyLakeman yes, this is what I am considering - if I merge all entities to be stored into 1 table Commented Jan 8, 2024 at 13:55

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.