1
votes

I have two models as below:

public class Person{

   public virtual int Id { get; set; }
   public virtual int BaseId { get; set; }
   public virtual string Name { get; set; }
   public virtual Employee Employee { get; set; }
}

public class Employee{

   public virtual int Id { get; set; }
   public virtual string Code{ get; set; }
   public virtual Person Person { get; set; }
}

Every Employee is a Person, but every Person is not necessarily an Employee. Relation between these two is type of One-One relation, but I need to make this relation between a non-primary key column(Person.BaseId) and the desired foreign key column(Employee.Id). In face the Id column in Employee model is the primary key and foreign key column at the same time.

I have this mapping configuration:

 public override void Configure(EntityTypeBuilder<Person> builder)
    {
        builder.HasKey(x => x.Id);
        builder.ToTable("tblPeople", "dbo");

        builder
            .HasOne(p => p.Employee)
            .WithOne(p => p.Person)
            .HasForeignKey<Employee>(p => p.Id)
            .HasPrincipalKey<Person>(p => p.BaseId);
    } 

  public override void Configure(EntityTypeBuilder<Employee> builder)
    {
        builder.HasKey(x => x.Id);
        builder.ToTable("tblEmployees", "dbo");
    }

When I try to generate the migration I get the following error:

The child/dependent side could not be determined for the one-to-one relationship between 'Employee.Person' and 'Person.Employee'. To identify the child/dependent side of the relationship, configure the foreign key property. If these navigations should not be part of the same relationship configure them without specifying the inverse. See http://go.microsoft.com/fwlink/?LinkId=724062 for more details.

I do not want to use the Data Annotation approach to solve this problem.

1
You do not need a principal key to establish an One-To-One relation - Ronald Haan
The fluent configuration is what it should be. The exception indicates that most likely the Configure method is not called (one of the reasons I don't like separate entity type configuration classes). - Ivan Stoev
@VahidFarahmandian There is always some explanation, except if you are hitting EF Core bug, which is not the case here. I have a clean project where I verify posts, so all I can do is to confirm you that your model (the way it is in the post) works fine when the fluent code is called, and generates the exact exception when the relationship configuration is commented out. - Ivan Stoev
@IvanStoev Yes you are right it works in a clean project! Problem is some where else, which I should find it! - Vahid Farahmandian
@IvanStoev Thank you for the hint, I have found the problem, solved it and posted the solution. - Vahid Farahmandian

1 Answers

1
votes

I found the solution, mistake was in my EntityTypeConfiguration classes design. I had the following design: For the case of simplicity I have cropped the code

public abstract class BaseMap<T, U> : IEntityTypeConfiguration<T> where T: BaseEntity<U>
{
    public virtual void Configure(EntityTypeBuilder<T> builder)
    {
        builder.HasKey(x => x.Id);
    }
}

public abstract class ChildBaseMap<T, U> : BaseMap<T, U> where T: ChildBaseEntity<U>
{
    public virtual void Configure(EntityTypeBuilder<T> builder)//<== virtual is wrong here as I need to override the parent Configure
    {
        base.Configure(builder);

        builder.Property(x => x.BaseId).IsRequired();
    }
}

public class PersonMap : ChildBaseMap<Person, int>
{
    public override void Configure(EntityTypeBuilder<Person> builder)
    {
      ....

Just override the Configure method, instead of define it as virtual in ChildBaseMap class solve the problem!