'EF Core: Map Many to Many relationship without navigation property

I'm trying to create a many to many relationship in entity Framework Core using Fluent API Here is my first model:

MyCalculationSelector.cs

  public int SortOrder { get; set; }
  public string UserString { get { return Name; } }

  private IList<CalculationType> _calculationTypes;
  public virtual IList<CalculationType> CalculationTypes
    {
       get { return _calculationTypes; }
       set { _calculationTypes = value; }
    }

And this is my second model:

MyCalculationType.cs

 public int SortOrder { get; set; }

 public string UserString
 {
    get { return Name; }
 }

 public int CalculationMethod { get; set; }

I remember that EF 6 could easily make the many to many relationship from Fluent API:

modelBuilder.Entity<MyCalculationSelector>().HasMany(x => x.MyCalculationTypes).WithMany();

Can we something like this be achieved in ef core? as of today, Hasmany-Withmany implementation is not possible



Solution 1:[1]

I have followed the documentation and have come up with this answer, please, someone who knows more than me and will correct me if I am wrong.

I first created my join table:

CalculationSelectorCalculationType.cs

public class CalculationSelectorCalculationType
    {
        public int CalculationSelector_Id { get; set; }
        public CalculationSelector CalculationSelector { get; set; }

        public int CalculationType_Id { get; set; }
        public CalculationType CalculationType { get; set; }
    }

CalculationSelector.cs

public CalculationSelector()
   {
      _calculationTypes = new List<CalculationSelectorCalculationType>();
      FontSize = 30;
   }
public int SortOrder { get; set; }
public string UserString { get { return Name; } }

private IList<CalculationSelectorCalculationType> _calculationTypes;
public virtual IList<CalculationSelectorCalculationType> CalculationTypes
    {
       get { return _calculationTypes; }
       set { _calculationTypes = value; }
    }

CalculationType.cs

 public int SortOrder { get; set; }

 public string UserString
 {
    get { return Name; }
 }

 public int CalculationMethod { get; set; }

...and finally my DbContext:

modelBuilder.Entity<CalculationSelectorCalculationType>().HasKey(p => new { p.CalculationSelector_Id, p.CalculationType_Id });
modelBuilder.Entity<CalculationSelectorCalculationType>().HasOne(p => p.CalculationSelector).WithMany(x => x.CalculationTypes).HasForeignKey(p => p.CalculationSelector_Id);
modelBuilder.Entity<CalculationSelectorCalculationType>().HasOne(p => p.CalculationType).WithMany().HasForeignKey(p => p.CalculationType_Id);

Solution 2:[2]

You can represent this with a private field or property:

modelBuilder.Entity<MyCalculationSelector>()
    .HasMany(x => x.MyCalculationTypes)
    .WithMany("NameOfThePrivateFieldOnMyCalculationType");

This way the navigation property is not exposed publically, but you can still use the Navigation Property on MyCalculationSelector without needing to traverse the intermediate join table.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dejosel
Solution 2