Entity Framework core - Many to Many relationship
Entity Framework core - Many to Many relationship
A many-to-many relationship occurs between domain entities when a one-to-many relationship between them works both ways. In my post the domain entity Baker can appear in many ProductTests and a ProductTest can contain many Bakers. This type of relationship is represented in a database by a join table.
Entities
A many-to-many relationship is defined in code by the inclusion of collection properties in each of the entities. The ProductTest property in the Baker class, and the Baker property in the ProductTest class:
public class ProductTest
{
public int Id { get; set; }
public string Title { get; set; }
/* EF many to many relation */
public ICollection<Baker> Bakers { get; set; }
}
public class Baker
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
/* EF many to many relation */
public ICollection<ProductTest> ProductTests { get; set; }
}
When you will try to create a migration using EF core you will get the error:
Unable to determine the relationship represented by navigation property ‘ProductTest.Bakers’ of type ‘ICollection<Bakers>’.
Either manually configure the relationship, or ignore this property using the ‘[NotMapped]’ attribute or by using ‘EntityTypeBuilder.Ignore’ in ‘OnModelCreating’.
New class
To resolve this, you have to create another class and map the relations. So that EF core understands the relationships between the domain entities and creates a new table in the database for the link.
public class ProductTestBaker
{
public int ProductTestId { get; set; }
public ProductTest ProductTest { get; set; }
public int BakerId { get; set; }
public Baker Baker { get; set; }
}
With this new class in your domain entity, you have to update the properties in both (ProductTest and Baker) classes that represents the relation. See the update below.
public class ProductTest
{
[..]
/* EF many to many relation */
public ICollection<ProductTestBaker> Bakers { get; set; }
}
public class Baker
{
[..]
/* EF many to many relation */
public ICollection<ProductTestBaker> ProductTests { get; set; }
}
When you again try to create the migration you again will get an error message. This time the error will be:
The entity type ‘ProductTestBaker’ requires a primary key to be defined.
This is essentially an expected error because there is indeed no primary key. With Entity Framework you can configure a single property to be the primary key of an entity (with [Key]). But there is also a possibility to configure multiple properties to be the key of an entity - this is known as a composite key. You can also see it as two properties (backend: database column) that together will represent a primary key
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProductTestBaker>().HasKey(productTestBaker =>
new { productTestBaker.ProductTestId, productTestBaker.BakerId });
}
You can now create a migration using Entity Framework and update your database.
You will see in the database that a new table is created named: ProductTestBaker.
With the columns: ProductTestId (PK, FK)
and BakerId (PK, FK)