Nathan
Nathan

Reputation: 437

Entity Framework Core 5 - Error with recursive structure

I'm trying to setup an entity framework class which has 4 fields that link back to others of the same type or are null. My class looks like this:

public class Patch : EntityBase
{
    [Key]
    public int PatchId { get; set; }

    [ForeignKey("NorthPatchId")]
    public virtual Patch NorthPatch { get; set; }

    [ForeignKey("SouthPatchId")]
    public virtual Patch SouthPatch { get; set; }

    [ForeignKey("EastPatchId")]
    public virtual Patch EastPatch { get; set; }

    [ForeignKey("WestPatchId")]
    public virtual Patch WestPatch { get; set; }
}

This works fine if I only have NorthPatch and SouthPatch but as soon as I add the third one, EastPatch, I get the following error while trying to do the migration:

System.InvalidOperationException: Unable to determine the relationship represented by navigation 'Patch.NorthPatch' of type 'Patch'.

Upvotes: 0

Views: 471

Answers (2)

Nathan
Nathan

Reputation: 437

@Lucutah answers the question as I wrote it but I wanted to post this other solution I found thats worth a look. It has similar results but will also automatically maintain the relationship between East/West and North/South entries. Though this may be no where near as performant depending on what you're trying to do.

public class Patch : EntityBase
{
    public int PatchId { get; set; }
    public virtual Patch NorthPatch { get; set; }
    public virtual Patch SouthPatch { get; set; }
    public virtual Patch EastPatch { get; set; }
    public virtual Patch WestPatch { get; set; }
}

In Context..

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Patch>().HasKey("PatchId");

        modelBuilder.Entity<Patch>()
           .HasOne(x => x.NorthPatch)
           .WithOne(x => x.SouthPatch)
           .HasForeignKey(typeof(Patch), "NorthPatchId");
        modelBuilder.Entity<Patch>()
           .HasOne(x => x.EastPatch)
           .WithOne(x => x.WestPatch)
           .HasForeignKey(typeof(Patch), "EastPatchId");
    }

Upvotes: 0

Lacutah
Lacutah

Reputation: 306

That's a pretty cool bug! I was able to duplicate, AND as a bonus found the bug reported and still open for EF Core.

Open Bug: https://github.com/dotnet/efcore/issues/21968

Similar Issue: Entity Framework Core One-One Self Referencing Relationship fails

Workaround: Remove the [ForeignKey] attributes, and use the following to your OnModelConfiguring for your context instead.

builder.Entity<Patch>()
    .HasOne(x => x.NorthPatch)
    .WithOne()
    .HasForeignKey(typeof(Patch), "NorthPatchId");

builder.Entity<Patch>()
    .HasOne(x => x.SouthPatch)
    .WithOne()
    .HasForeignKey(typeof(Patch), "SouthPatchId");

builder.Entity<Patch>()
    .HasOne(x => x.EastPatch)
    .WithOne()
    .HasForeignKey(typeof(Patch), "EastPatchId");

builder.Entity<Patch>()
    .HasOne(x => x.WestPatch)
    .WithOne()
    .HasForeignKey(typeof(Patch), "WestPatchId");

Upvotes: 1

Related Questions