Search code examples
c#asp.net-mvcentity-frameworkasp.net-web-apief-code-first

Unable to determine the principal end of an association between the types 'X' and 'X'


I'm using Entity Framework and here it's my entity Model:

Public class Document
{
    Public int Id { get; set; }
    Public Document Parent { get; set; }
}

and as you see that it has a self-reference property.

Now I'm trying to add another self-reference property like this:

Public class Document
{
    Public int Id { get; set; }
    Public Document Parent { get; set; }
    Public Document SrcDocument { get; set; }
}

But unfortunately I've faced with below error:

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


Solution

  • Entity Framework Code-First conventions are assuming that Document and Document belong to the same relationship and are the inverse navigation properties of each other. Because both navigation properties are references (not collections) EF infers a one-to-one relationship.

    Since you actually want two one-to-many relationships you must override the conventions. Just override OnModelCreating method of the context and put there what's your idea about new cycle-relation like this:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Document>().HasRequired(p => p.SrcDocument).WithMany();
        base.OnModelCreating(modelBuilder);
    }
    

    Update

    modelBuilder.Entity<Document>().HasRequired(p => p.SrcDocument).WithMany(); say to Entity Framework the SrcDocument has a one-to-many relation with itself.

    and also you can use below code:

    modelBuilder.Entity<Document>().HasOptional(p => p.SrcDocument).WithMany();
    

    to make a zero-to-many relation.

    and with this:

    modelBuilder.Entity<Document>().HasOptional(p => p.SrcDocument).WithOptionalDependent();
    

    you can define a one-to-zero relation.

    It'll be worked.