Many-to-many Relationship

Many-to-many Relationship

Earlier in Entity Framework, the many-to-many relationship was classified as two one-to-many relationships. To make it work the developer must create a joining entity class.
Now in Entity Framework Core 5.0, it will have full support for many-to-many relations without explicitly mapping the join table.
  • The navigation properties skip the join table and directly point to the other entity.
  • It will result in writing cleaner queries and simplify the use of the query result.
Let's consider the following model.
1
public class Movie
2
{
3
public int MovieId { get; set; }
4
public string Name{ get; set; }
5
public Actor Actor { get; set; }
6
public List<Genre> Genres { get; set; }
7
}
8
​
9
public class Genre
10
{
11
public int GenreId { get; set; }
12
public string GenreName { get; set; }
13
public List<Movie> Movies{ get; set; }
14
}
Copied!
As you can see that Movie class contains a collection of Genres, and Genre class contains a collection of Movies. EF Core 5.0 recognizes this as a many-to-many relationship by convention and there is no need for configuration in OnModelCreating.
1
public class MyEntityContext : DbContext
2
{
3
protected override void OnConfiguring(DbContextOptionsBuilder opBuilder)
4
{
5
opBuilder.UseSqlServer("Data Source=(localdb)\\ProjectsV13;Initial Catalog=MyContextDB;");
6
}
7
​
8
public DbSet<Movie> Movies { get; set; }
9
public DbSet<Genre> Genres { get; set; }
10
​
11
}
Copied!
When you create migration or call the EnsureCreatedmethod, it will create the following tables including the join table.
1
CREATE TABLE [dbo].[Movies] (
2
[MovieId] INT IDENTITY (1, 1) NOT NULL,
3
[Name] NVARCHAR (MAX) NULL,
4
CONSTRAINT [PK_Movies] PRIMARY KEY CLUSTERED ([MovieId] ASC)
5
);
6
​
7
CREATE TABLE [dbo].[Genres] (
8
[GenreId] INT IDENTITY (1, 1) NOT NULL,
9
[GenreName] NVARCHAR (MAX) NULL,
10
CONSTRAINT [PK_Genres] PRIMARY KEY CLUSTERED ([GenreId] ASC)
11
);
12
​
13
CREATE TABLE [dbo].[GenreMovie] (
14
[GenresGenreId] INT NOT NULL,
15
[MoviesMovieId] INT NOT NULL,
16
CONSTRAINT [PK_GenreMovie] PRIMARY KEY CLUSTERED ([GenresGenreId] ASC, [MoviesMovieId] ASC),
17
CONSTRAINT [FK_GenreMovie_Genres_GenresGenreId] FOREIGN KEY ([GenresGenreId]) REFERENCES [dbo].[Genres] ([GenreId]) ON DELETE CASCADE,
18
CONSTRAINT [FK_GenreMovie_Movies_MoviesMovieId] FOREIGN KEY ([MoviesMovieId]) REFERENCES [dbo].[Movies] ([MovieId]) ON DELETE CASCADE
19
);
Copied!
Let's insert some movies and genres.
1
using (var context = new MyEntityContext())
2
{
3
context.Database.EnsureCreated();
4
​
5
var comedy = new Genre() { GenreName = "Comedy" };
6
var action = new Genre() { GenreName = "Action" };
7
var horror = new Genre() { GenreName = "Horror" };
8
var scifi = new Genre() { GenreName = "Sci-fi" };
9
​
10
context.AddRange(
11
new Movie() { Name = "Avengers", Genres = new List<Genre>() { action, scifi } },
12
new Movie() { Name = "Satanic Panic", Genres = new List<Genre>() { comedy, horror } });
13
​
14
context.SaveChanges();
15
​
16
}
Copied!
EF will then automatically create rows in the join table.
Copy link