Resumo : neste tutorial, você aprenderá como usar o inner join para consultar dados de duas ou mais tabelas no EF Core.
Introdução ao EF Core Inner Join
Um departamento pode ter um ou mais funcionários, enquanto um funcionário pertence a um departamento. O relacionamento entre o departamento e o funcionário é um relacionamento um-para-muitos .
A Department
entidade mapeia para a Departments
tabela enquanto a Employee
entidade mapeia para a Employees
tabela.
Aqui está o diagrama do banco de dados das tabelas Departments
e Employees
:
As entidades Department
e Employee
são as seguintes:
public class Department
{
public int Id { get; set; }
public required string Name { get; set; }
}
namespace HR;
public class Employee
{
public int Id { get; set; }
public required string FirstName { get; set; }
public required string LastName { get; set; }
public required decimal Salary { get; set; }
public required DateTime JoinedDate { get; set; }
// Foreign key property to the Department
public int DepartmentId { get; set; }
// Reference navigation to Department
public Department Department { get; set; } = null!;
// Reference navigation to EmployeeProfile
public EmployeeProfile? Profile { get; set; }
// collection navigation to Employee
public List<Skill> Skills { get; set; } = new();
}
Linguagem de código: C# ( cs )
Ao consultar os dados dos funcionários, você pode querer obter os departamentos que pertencem aos funcionários. Para fazer isso, você usa o Include()
método do Employees
DbSet
.
Por exemplo, o programa a seguir usa o Include()
método para obter os funcionários com seus departamentos e classificá-los pelo primeiro nome:
using HR;
using static System.Console;
using Microsoft.EntityFrameworkCore;
using var context = new HRContext();
// Get employees & departments
var employees = context.Employees.Include(e => e.Department)
.OrderBy(e => e.FirstName)
.ToList();
foreach (var e in employees)
{
WriteLine($"{e.FirstName} {e.LastName} - {e.Department.Name}");
}
Linguagem de código: C# ( cs )
Saída:
Abigail Adams - Marketing
Addison Hill - Engineering
Aiden Wright - Marketing
Alexander Green - Finance
Alexander Young - Finance
Amelia Scott - Operations
...
Linguagem de código: C# ( cs )
Nos bastidores, o EF Core gera uma instrução SQL que usa uma junção interna para consultar dados das tabelas Employees
e :Departments
SELECT
[e].[Id],
[e].[DepartmentId],
[e].[FirstName],
[e].[JoinedDate],
[e].[LastName],
[e].[Salary],
[d].[Id],
[d].[Name]
FROM
[Employees] AS [e]
INNER JOIN [Departments] AS [d] ON [e].[DepartmentId] = [d].[Id]
ORDER BY
[e].[FirstName]
Linguagem de código: C# ( cs )
A instrução SQL une Employees
a Departments
tabela combinando os valores na DepartmentId
coluna da Employees
tabela com os valores na Id
coluna da Department
tabela.
EF Core Inner Join em um relacionamento muitos para muitos
Um funcionário pode ter muitas habilidades e uma habilidade pode ser possuída por muitos funcionários. O relacionamento entre o funcionário e a habilidade é um relacionamento muitos para muitos .
O seguinte mostra a Skill
classe de entidade:
public class Skill
{
public int Id { get; set; }
public required string Title { get;set; }
// collection navigation to Employee
public List<Employee> Employees { get; set; } = new();
}
Linguagem de código: C# ( cs )
Aqui está o diagrama do banco de dados que modela o relacionamento muitos-para-muitos entre entidades Employee
e :Skill
Para obter funcionários com suas habilidades, você pode usar o Include()
método Employees
DbSet
a seguir:
using HR;
using static System.Console;
using Microsoft.EntityFrameworkCore;
using var context = new HRContext();
var employees = context.Employees.Include(e => e.Skills)
.OrderBy(e => e.FirstName)
.ToList();
foreach (var e in employees)
{
WriteLine($"{e.FirstName} {e.LastName}");
foreach (var skill in e.Skills)
{
WriteLine($"- {skill.Title}");
}
}
Linguagem de código: C# ( cs )
Saída:
Abigail Adams
- Marketing Strategy
- Market Segmentation
Addison Hill
- Product Design
- Quality Assurance
Aiden Wright
- Market Trend Analysis
- Brand Development
...
Linguagem de código: C# ( cs )
Neste exemplo, o EF Core primeiro une a EmployeeSkill
tabela com a Skills
tabela usando uma junção interna em uma subconsulta . E então ele une a Employees
tabela com o conjunto de resultados retornado pela subconsulta usando um left join . Isso significa que a consulta retornará todos os funcionários, tenham ou não habilidades.
SELECT
[e].[Id],
[e].[DepartmentId],
[e].[FirstName],
[e].[JoinedDate],
[e].[LastName],
[e].[Salary],
[t].[EmployeesId],
[t].[SkillsId],
[t].[Id],
[t].[Title]
FROM
[Employees] AS [e]
LEFT JOIN (
SELECT
[e0].[EmployeesId],
[e0].[SkillsId],
[s].[Id],
[s].[Title]
FROM
[EmployeeSkill] AS [e0]
INNER JOIN [Skills] AS [s] ON [e0].[SkillsId] = [s].[Id]
) AS [t] ON [e].[Id] = [t].[EmployeesId]
ORDER BY
[e].[FirstName],
[e].[Id],
[t].[EmployeesId],
[t].[SkillsId]
Linguagem de código: C# ( cs )
Usando múltiplas junções
Para obter os funcionários e seus departamentos e habilidades, você pode usar vários Include()
métodos na mesma consulta:
using HR;
using static System.Console;
using Microsoft.EntityFrameworkCore;
using var context = new HRContext();
var employees = context.Employees.Include(e => e.Department)
.Include(e => e.Skills)
.OrderBy(e => e.FirstName)
.ToList();
foreach (var e in employees)
{
WriteLine($"{e.FirstName} {e.LastName} - {e.Department.Name}");
foreach (var skill in e.Skills)
{
WriteLine($"- {skill.Title}");
}
}
Linguagem de código: C# ( cs )
Saída:
Abigail Adams - Marketing
- Marketing Strategy
- Market Segmentation
Addison Hill - Engineering
- Product Design
- Quality Assurance
Aiden Wright - Marketing
- Market Trend Analysis
- Brand Development
Linguagem de código: C# ( cs )
O EF Core gera uma instrução SQL que possui várias cláusulas de junção. Primeiro, ele une a Employees
tabela à Departments
tabela usando uma junção interna. E então ele se junta a uma subconsulta que inclui EmployeeSkill
tabelas Skills
usando uma junção à esquerda:
SELECT
[e].[Id],
[e].[DepartmentId],
[e].[FirstName],
[e].[JoinedDate],
[e].[LastName],
[e].[Salary],
[d].[Id],
[d].[Name],
[t].[EmployeesId],
[t].[SkillsId],
[t].[Id],
[t].[Title]
FROM
[Employees] AS [e]
INNER JOIN [Departments] AS [d] ON [e].[DepartmentId] = [d].[Id]
LEFT JOIN (
SELECT
[e0].[EmployeesId],
[e0].[SkillsId],
[s].[Id],
[s].[Title]
FROM
[EmployeeSkill] AS [e0]
INNER JOIN [Skills] AS [s] ON [e0].[SkillsId] = [s].[Id]
) AS [t] ON [e].[Id] = [t].[EmployeesId]
ORDER BY
[e].[FirstName],
[e].[Id],
[d].[Id],
[t].[EmployeesId],
[t].[SkillsId]
Linguagem de código: C# ( cs )
Resumo
- Use
DbSet
Include()
o método para formar uma junção interna (ou junção esquerda) no EF Core.