Ef Core One-To-Many with join table

Viewed 1458

I have two models which both have a collection of the same third model. Ef Core 5 now creates a foreign key for both models on the collection model but is there a way to let it generate a join table for each relationship without explicitly having a model for the join table?

My Models:

public class Model1 {
    // ...
    public List<Model3> collection;
}

public class Model2 {
    // ...
    public List<Model3> collection;
}

public class Model3 {
    // ...
}

I want the db to look something like this:

Table: Model1

Table: Model2

Table: Model3

Table: Model3Model1 (JoinTable)

  • Model3Id
  • Model1Id

Table: Model3Model2 (JoinTable)

  • Model3Id
  • Model2Id

But I don't want explicit Types for those join tables. I know that EFCore is able to infer those join tables for many-to-many relationship so I was wondering if there is a way to do this for one-to-many as well.

1 Answers

I don't think it's possible. The best compromise is private properties in Model3 like :

public class MyContext : DbContext
{
    public DbSet<Model1> Model1 { get; set; }
    public DbSet<Model2> Model2 { get; set; }
    public DbSet<Model3> Model3 { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Model3>()
            .HasMany<Model1>("Collection1")
            .WithMany(m1 => m1.Collection)
            .UsingEntity(j => {
                j.ToTable("Model3Model1");
                j.Property("Collection1Id").HasColumnName("Model3Id");
                j.Property("CollectionId").HasColumnName("Model1Id");
            });
        modelBuilder.Entity<Model3>()
            .HasMany<Model2>("Collection2")
            .WithMany(m2 => m2.Collection)
            .UsingEntity(j => {
                j.ToTable("Model3Model2");
                j.Property("Collection2Id").HasColumnName("Model3Id");
                j.Property("CollectionId").HasColumnName("Model2Id");
            });
    }
}

public class Model1
{
    public int Id { get; set; }
    public List<Model3> Collection { get; set; }
}

public class Model2
{
    public int Id { get; set; }
    public List<Model3> Collection { get; set; }
}

public class Model3
{
    public int Id { get; set; }
    private List<Model1> Collection1 { get; set; }
    private List<Model2> Collection2 { get; set; }
}

The generated join entity has a navigation property, where the name is + "Id". The tricky part is to set the desired column name.

Related