Search code examples
c#.netdatabaseentity-frameworkorm

Can I define a one-to-many relationship on a complex type in Entity Framework Code First?


I have a situation like the following toy example:

public class Person
{
    public Guid Id { get; set; }
    public string FullName { get; set; }
    public ContactInfo ContactInfo { get; set; }
}

public class ContactInfo
{
    public string EmailAddress { get; set; }
    public IEnumerable<Address> PostalAddresses { get; set; }
}

public class Address
{
    public Guid Id { get; set; }
    public Guid PersonId { get; set; }
    /* ... other properties ... */
}

The real situation is much more complex and I would really like the equivalent of the PostalAddresses property to be on ContactInfo instead of Person.

Is this possible using Entity Framework Code First?


EDIT

Basically, I want the above to be serialized into the following table structure:

  • table: People

    • Id
    • FullName
    • ContactInfo_EmailAddress
  • table: Address

    • Id
    • PersonId
    • ...

So the problem is that I need to have the IEnumerable<Address> collection to be on the ContactInfo complex type instead of the root type, Person. When I save a Person object, no Address rows are added to the database.


Solution

  • Your question seems perfectly clear.

    I'm not an expert, but according to How to specify a relation on a complex type? what you're trying to do is not possible. A ComplexType cannot have navigational properties.

    I guess the workaround is to define ContactInfo as an entity, instead of a complex type. So ContactInfo will have a PK and it's own table.

    Maybe somebody else knows a better solution?

    By the way, I tried to do something similar. My (simplified) domain:

    Application

    • Id : int
    • Candidate : Candidate
    • Resume : Resume <== I prefer to not have a separate table for this class, but how to achieve this??

    Resume

    • Experiences : [Experience]
    • Trainings : [Training]

    Experience

    • Id: int
    • Description: string

    Training

    • Id: int
    • Description: string

    Candidate

    • Id: int
    • Name: string

    I ended up giving Resume an Id too, but the result is a redundant Review table consisting of just one column, i.e. the resume Id (which equals the application Id).