Search code examples
entity-frameworkef-code-firstentity-framework-6fluent-entity-framework

Defining navigation from Person to Country but not from Country to Persons using the Fluent syntax


I have the following relationship between Person and Country defined by convention. This works perfectly.

public class Person
{
    public long PersonId {get; set;}
    public string Name {get; set;}

    public long CountryId {get; set;}
    public virtual Country Country {get; set;}
}

public class Country
{
    public long CountryId {get; set;}
    public string Name {get; set;}
}

I now wish to change the name of the property Country to something else. As I understand it this means the relationship does not work anymore by convention. So I wish to define it using the fluent syntax.

I found this reference but it is not clear to me how I should handle this exact scenario since in their examples both sides of the relation contain a foreign key or collection.

There is a section "Configuring a Relationship with One Navigation Property" which makes me think it should look like this:

modelBuilder.Entity<Patient>() 
    .HasRequired(t => t.Country) 
    .WithRequiredPrincipal();

However, whenever when storing countries this results in the following exception

{"The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_dbo.Countries_dbo.Patients_CountryId\". The conflict occurred in database \"TESTS_ffbe7a6e73a747ce8cda71f963bb20b7\", table \"dbo.Patients\", column 'PatientId'.\r\nThe statement has been terminated."}

So my question are now: - How do I define the above 'by convention' relationship using fluent syntax? - Is the CountryId property still required when using the fluent syntax?


Solution

  • In your sample code you're expressing this:

    • Entity<Patient>().HasRequired(t => t.Country): each patient must have a related country
    • .WithRequiredPrincipal(): each country must have a related patient

    I suppose you don't need each country to have one or more related patients. So, do this:

      modelBuilder.Entity<Person>()
                  .HasRequired(p => p.Country)
                  .WithMany();
    

    This means that each person must have a country, and each country can have many related persons. And you don't specify a nvaigation back from country to person.

    To understand this kind of fluent API relationships take into account that the first function (i.e HasRequired) is the relationship from the first entity to the second entity. And then, the second function (i.e. WithXXX) is the relationship back from the second entity to the first one.

    Thanks to the Fluent API it's easy to express any kind of relationship without making mistakes. Besides there are overloads with or without paramteres that allow you to specify the navigation properties, or omit them if they're not present. For example, if you needed to navigate back from country to persons, using a Persons property, it would look like this:

      WithMany(c => c.Persons)