Reputation: 245
I'm quite new to Entity Framework and am picking it up with the Core version. I'm trying to understand how to customise model relationships.
My basic model is that I have a Company entity, and a Contact entity. A Company can have many Contacts. A company can a KeyContact, which must be one of the associated contacts, but is not required.
Thus there is a One to Many relationship, but also a One to One relationship. I've tried to implement this as below (removed most other fields for clarity);
public class Company
{
public int Id { get; set; }
public int? KeyContactId { get; set; }
public ICollection<Contact> Contacts { get; set; }
public Contact KeyContact { get; set; }
}
public class Contact
{
public int Id { get; set; }
public int CompanyId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Company Company { get; set; }
}
It fails to add this migration with the message;
Unable to determine the relationship represented by navigation property 'Company.Contacts' of type 'ICollection'. Either manually configure the relationship, or ignore this property from the model.
I can kinda see why it's complaining about this, but I'm not sure if there's a way with the model builder I can configure this, or whether it's an invalid pattern. My model builder is currently just basic;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Company>().ToTable("Company");
modelBuilder.Entity<Contact>().ToTable("Contact");
}
I know I could just have a flag to say IsKeyContact in the contact table, but I like the idea of having the navigation property in the company entity. So I'm wondering how sugary Entity can be.
Any help much appreciated.
Thanks,
Nick
Upvotes: 7
Views: 3028
Reputation: 83
The exception is avoided by adding the following line to the OnModelCreating
method:
modelBuilder.Entity<Company>().HasMany(p => p.Contacts).WithOne(d => d.Company).HasForeignKey(d => d.CompanyId);
This configures the Company.Contacts
-Contact.Company
relation. By default, the Company.KeyContact
relation is configured as if the following line would be within the OnModelCreating
method:
modelBuilder.Entity<Company>().HasOne(e => e.KeyContact).WithMany().HasForeignKey(e => e.KeyContactId);
Hence a Contact can be the KeyContact of more than one Company.
In order to ensure that a Contact can be the KeyContact of at most one Company the Company.KeyContact
relation could be configured by the following line within the OnModelCreating
method:
modelBuilder.Entity<Company>().HasOne(e => e.KeyContact).WithOne().HasForeignKey<Company>(e => e.KeyContactId);
But note: This will not ensure that the KeyContact is a member of the Contacts.
Upvotes: 4