I am currently upgrading a large database-first project to EF Core 6.0. Details of the breaking EF Core 6.0 scaffolding change described in the title can be found here: https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-6.0/breaking-changes#many-to-many. I am also aware of the mitigations available and the open efcore issue to optionally restore join tables.
From the article above:
It is very rare that the join entity type needs to be used directly when it contains only two foreign keys for the many-to-many relationships.
This is simply not true in the project I am working on. My questions are:
For example, consider a many-to-many relationship between a Person and a Thing. In EF Core 6.0 the join entity is no longer available:
public partial class PersonThing
{
public int PersonId { get; set; }
public int ThingId { get; set; }
public virtual Person Person { get; set; }
public virtual Thing Thing { get; set; }
}
And the tables are mapped with a many-to-many relationship instead:
public partial class Person
{
public Person()
{
Thing = new HashSet<Thing>();
}
public int PersonId { get; set; }
public string PersonName { get; set; }
public virtual ICollection<Thing> Thing { get; set; }
}
public partial class Thing
{
public Thing()
{
Person = new HashSet<Person>();
}
public int ThingId { get; set; }
public string ThingName { get; set; }
public virtual ICollection<Person> Person { get; set; }
}
Previously it was possible to update the relationship between existing Persons and Things using ids only:
public void UpdateThings(IReadOnlyCollection<int> thingIds)
{
// sync PersonThings
var syncQueue = SynchronisationHelper.GetSynchronisationQueue(thingIds, _model.PersonThing, (s, d) => s == d.ThingId);
foreach (var thingId in syncQueue.Inserts)
{
var personThing = new Database.Model.PersonThing
{
PersonId = _model.PersonId,
ThingId = thingId
};
_model.PersonThing.Add(personThing);
}
foreach (var personThing in syncQueue.Deletes)
{
_context.PersonThing.Remove(personThing);
}
}
What is the alternative to this without access to the join entity type? Must you load the related entity from context just to create the relationship, or is there a better way of achieving this?
public void UpdateThings(IReadOnlyCollection<int> thingIds)
{
// sync Things
var syncQueue = SynchronisationHelper.GetSynchronisationQueue(thingIds, _model.Thing, (s, d) => s == d.ThingId);
foreach (var thingId in syncQueue.Inserts)
{
var thing = _context.Thing.Single(t => thingId == t.ThingId);
_model.Thing.Add(thing);
}
foreach (var thing in syncQueue.Deletes)
{
_model.Thing.Remove(thing);
}
}
Based on this comment on the open efcore issue to optionally restore join tables, I am satisfied that using join entity types is a perfectly valid database-first approach, and using them (or not) is a question of preference / style. There are already mitigations available to map join entity types using scaffolding in EF Core 6.0, hopefully the issue is addressed so this can be achieved without a workaround.