Many to many self join through junction table

Posted by Peter on Stack Overflow See other posts from Stack Overflow or by Peter
Published on 2014-08-20T19:41:44Z Indexed on 2014/08/21 10:20 UTC
Read the original article Hit count: 192

Filed under:
|

I have an EF model that can self-reference through an intermediary class to define a parent/child relationship. I know how to do a pure many-to-many relationship using the Map command, but for some reason going through this intermediary class is causing problems with my mappings. The intermediary class provides additional properties for the relationship. See the classes, modelBinder logic and error below:

public class Equipment
{        
    [Key]
    public int EquipmentId { get; set; }

    public virtual List<ChildRecord> Parents { get; set; }
    public virtual List<ChildRecord> Children { get; set; }
}

public class ChildRecord
{
    [Key]
    public int ChildId { get; set; }

    [Required]
    public int Quantity { get; set; }

    [Required]
    public Equipment Parent { get; set; }

    [Required]
    public Equipment Child { get; set; }
}

I've tried building the mappings in both directions, though I only keep one set in at a time:

        modelBuilder.Entity<ChildRecord>()
            .HasRequired(x => x.Parent)
            .WithMany(x => x.Children )
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<ChildRecord>()
            .HasRequired(x => x.Child)
            .WithMany(x => x.Parents)
            .WillCascadeOnDelete(false);

OR

        modelBuilder.Entity<Equipment>()
            .HasMany(x => x.Parents)
            .WithRequired(x => x.Child)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<Equipment>()
            .HasMany(x => x.Children)
            .WithRequired(x => x.Parent)
            .WillCascadeOnDelete(false);

Regardless of which set I use, I get the error: The foreign key component 'Child' is not a declared property on type 'ChildRecord'. Verify that it has not been explicitly excluded from the model and that it is a valid primitive property. when I try do deploy my ef model to the database.

If I build it without the modelBinder logic in place then I get two ID columns for Child and two ID columns for Parent in my ChildRecord table. This makes sense since it tries to auto create the navigation properties from Equipment and doesn't know that there are already properties in ChildRecord to fulfill this need.

I tried using Data Annotations on the class, and no modelBuilder code, this failed with the same error as above:

    [Required]
    [ForeignKey("EquipmentId")]
    public Equipment Parent { get; set; }

    [Required]
    [ForeignKey("EquipmentId")]
    public Equipment Child { get; set; }

AND

    [InverseProperty("Child")]
    public virtual List<ChildRecord> Parents { get; set; }
    [InverseProperty("Parent")]
    public virtual List<ChildRecord> Children { get; set; }

I've looked at various other answers around the internet/SO, and the common difference seems to be that I am self joining where as all the answers I can find are for two different types.

© Stack Overflow or respective owner

Related posts about c#

Related posts about entity-framework