-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support self-referencing many-to-many with a single navigation #23348
Comments
The approach should be the same as with other many-to-many relationships. Have you run into any issues? |
Yes, my scenario simplified is basically:
My OnModelCreating override throws a stackoverflow exception at this statement:
|
I see. EF only allows a navigation to be used once in a relationship. It might seem artificial for your scenario, but two navigations are needed to establish a relationship. What you are looking for is more akin to a grouping, which isn't supported via a navigation. |
In case it helps anyone, the example below shows how to map a self-referencing many-to-many relationship using EF Core 5 syntax. I've tried to keep the mapping as minimal as possible, using defaults where possible. using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace ManyToMany
{
internal class Program
{
private static void Main()
{
using var dbContext = new AppDbContext();
dbContext.Database.EnsureDeleted();
dbContext.Database.EnsureCreated();
var workItem1 = new WorkItem {Description = "W1"};
var workItem2 = new WorkItem {Description = "W2"};
var workItem3 = new WorkItem {Description = "W3"};
workItem1.RelatedTo = new List<WorkItem> {workItem2, workItem3};
workItem3.RelatedTo = new List<WorkItem> {workItem1, workItem2};
dbContext.AddRange(workItem1, workItem2, workItem3);
dbContext.SaveChanges();
var workItems = dbContext.WorkItems.ToArray();
foreach (var workItem in workItems)
{
Console.Write(workItem.Description);
Console.Write(" => ");
if (workItem.RelatedTo != null)
{
Console.Write(string.Join(", ", workItem.RelatedTo.Select(x => x.Description)));
}
Console.Write(" <= ");
if (workItem.RelatedFrom != null)
{
Console.Write(string.Join(", ", workItem.RelatedFrom.Select(x => x.Description)));
}
Console.WriteLine();
}
}
}
public class AppDbContext : DbContext
{
public DbSet<WorkItem> WorkItems { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);
optionsBuilder.UseNpgsql(
"Host=localhost;Port=5432;Database=ExampleDB;User ID=postgres;Password=postgres");
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<WorkItem>()
.HasMany(workItem => workItem.RelatedFrom)
.WithMany(workItem => workItem.RelatedTo)
.UsingEntity<WorkItemToWorkItem>(
right => right
.HasOne(joinEntity => joinEntity.FromItem)
.WithMany(),
left => left
.HasOne(joinEntity => joinEntity.ToItem)
.WithMany());
}
}
public class WorkItem
{
public int Id { get; set; }
public string Description { get; set; }
public IList<WorkItem> RelatedFrom { get; set; }
public IList<WorkItem> RelatedTo { get; set; }
}
public class WorkItemToWorkItem
{
public WorkItem FromItem { get; set; }
public WorkItem ToItem { get; set; }
}
} Output:
|
We don't plan to support this fully in EF Core. The best workaround would be to Map the navigation to a query |
Hello,
What would be the recommended method for self-referencing many to many relationships?
For example in an eCommerce type environment handling 'Related Products'
Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
The text was updated successfully, but these errors were encountered: