user2240973
user2240973

Reputation:

OneToOne Inverse Property in same class is possible? How?

I have this class with the following inverse properties:

public class Person
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }

    public int FatherId { get; set; }
    [ForeignKey("FatherId")]
    public Person Father { get; set; }

    public int MotherId { get; set; }
    [ForeignKey("MotherId")]
    public Person Mother { get; set; }
}

Sorry if this is a repetitive question, but I'm unable to solve and understand this.

When trying to create the database I get the error message:

Unable to determine the principal end of an association between the types 'TestEFInverseProperty.Person' and 'TestEFInverseProperty.Person'. The principal end of >this association must be explicitly configured using either the relationship fluent API or >data annotations.

Please, how I can fix it?

If this is not the best way to do this kind of relationship, how do you advise me?

Upvotes: 1

Views: 1017

Answers (1)

danludwig
danludwig

Reputation: 47375

I think you are going to have to make both FatherId and MotherId a System.Nullable<int>. The way you have it, a Person cannot exist unless it has both a Father and a Mother, and both Father and Mother must each also have Father and Mother, and so on. At some point you have to stop and allow the system to have a Person without a Father or Mother, which means your foreign keys need to be nullable.

Also, your navigation properties should be marked virtual.

Here is how you could do it using the fluent API:

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }

    public int? FatherId { get; set; }
    public virtual Person Father { get; set; }

    public int? MotherId { get; set; }
    public virtual Person Mother { get; set; }
}

public class PersonTypeConfiguration : EntityTypeConfiguration<Person>
{
    public PersonTypeConfiguration()
    {
        HasOptional(x => x.Mother).WithMany().HasForeignKey(x => x.MotherId);
        HasOptional(x => x.Father).WithMany().HasForeignKey(x => x.Father);
    }
}

The above is telling EF that the Mother and Father sides of the relationships are the principal ends, with the child Person being on the dependent end. This is because given any one-to-many relationship, the many side is the principal, and the one side is the dependent. It doesn't matter if the relationship is reflexive (or as you say inverse) to the same entity.

Upvotes: 1

Related Questions