Relacionamentos um-para-muitos do EF Core

Resumo : neste tutorial, você aprenderá sobre relacionamentos um-para-muitos e como implementá-los no EF Core.

Introdução aos relacionamentos um-para-muitos

No banco de dados relacional, um relacionamento um-para-muitos é um tipo comum de relacionamento entre duas tabelas em que uma linha de uma tabela pode ser associada a várias linhas de outra tabela.

Por exemplo, um departamento pode ter vários funcionários enquanto um funcionário pertence a um departamento. Portanto, o Departmentstem um relacionamento um-para-muitos com a Employeestabela.

O relacionamento um-para-muitos também é conhecido como relacionamento pai-filho. A Departmentsé chamada de tabela pai, enquanto a Employeestabela é chamada de tabela filha.

Para estabelecer o relacionamento um-para-muitos entre as tabelas Departmentse Employees, a Employeestabela precisa ter uma coluna de chave estrangeiraDepartmentId chamada que faça referência à Idcoluna da Employeestabela:

Se a DepartmentIdcoluna aceitar NULL, você poderá inserir uma linha na Employeestabela sem especificar uma linha correspondente na Departmentstabela. Neste caso, o funcionário não pertence a nenhum departamento.

No entanto, se a DepartmentIdcoluna não aceitar NULL, você precisará usar um Idda Departmentstabela para inserir uma nova linha na Employeestabela. Neste caso, o funcionário deve pertencer a um departamento específico. Em outras palavras, você precisa ter pelo menos uma linha na Departmentstabela antes de poder inserir linhas na Employeestabela.

Demonstraremos cenários típicos para que você possa modelar relacionamentos um-para-muitos entre entidades. Para cenários abrangentes, você pode consultar esta página .

A modelagem exigia relacionamento um-para-muitos

Veja a seguir como modelar um relacionamento um-para-muitos necessário entre as entidades Departmente :Employee

public class Department
{
    public int Id { get; set; }
    public required string Name { get; set; }

    // Collection navigation containing children
    public ICollection<Employee> Employees { get; set; }
}

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; }
    
    // Required foreign key property    
    public int DepartmentId  {   get; set; } 

    //  Required reference navigation to parent 
    public Department Department {  get; set; } = null!;
}Linguagem de código:  C#  ( cs )

Neste exemplo:

  • A Departmentclasse possui uma propriedade que é uma coleção de Employeeobjetos.
  • A Employeeclasse tem duas propriedades DepartmentIde Department. O DepartmentIdé chamado de propriedade de chave estrangeira , que é marcado como obrigatório. Isso torna o relacionamento um-para-muitos obrigatório porque cada um Employeedeve se associar a pelo menos um arquivo Department. A Departmentpropriedade é conhecida como propriedade de navegação .

Com base neste modelo, o EF Core gera a tabela Departmentse Employeesno banco de dados SQL Server com a seguinte estrutura:

CREATE TABLE [dbo].[Departments] (
    [Id]   INT            IDENTITY (1, 1) NOT NULL,
    [Name] NVARCHAR (MAX) NOT NULL,
    CONSTRAINT [PK_Departments] PRIMARY KEY CLUSTERED ([Id] ASC)
);

GO 
CREATE TABLE [dbo].[Employees] (CREATE TABLE [dbo].[Employees] (
    [Id]           INT             IDENTITY (1, 1) NOT NULL,
    [FirstName]    NVARCHAR (MAX)  NOT NULL,
    [LastName]     NVARCHAR (MAX)  NOT NULL,
    [Salary]       DECIMAL (18, 2) NOT NULL,
    [JoinedDate]   DATETIME2 (7)   NOT NULL,
    [DepartmentId] INT             NOT NULL,
    CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_Employees_Departments_DepartmentId] FOREIGN KEY ([DepartmentId]) REFERENCES [dbo].[Departments] ([Id]) ON DELETE CASCADE
);


GO
CREATE NONCLUSTERED INDEX [IX_Employees_DepartmentId]
    ON [dbo].[Employees]([DepartmentId] ASC);
Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Observe que a DepartmentIdcoluna da Employeestabela não é NULL. Além disso, é uma chave estrangeira que faz referência à Idcoluna da Departmentstabela.

Modelando o relacionamento um-para-muitos opcional

O seguinte altera a DepartmentIdpropriedade de chave estrangeira e Departmentsa propriedade de navegação da Employeeclasse para anulável:

public class Department
{
    public int Id { get; set; }
    public required string Name { get; set; }
    public ICollection<Employee> Employees { get; set; }
}
public class Employee
{
    public int Id { get; set; }
    public required string FirstName {  get; set; }
    public required string LastName {  get; set; }
    public required DateTime JoinedDate { get; set; }
    
    public int? DepartmentId  {   get;set; }
    public Department? Department {  get; set; }
}Linguagem de código:  C#  ( cs )

Como as propriedades DepartmentIdand Departmentsão anuláveis, você pode criar um Employeeobjeto sem um Department.

O EF Core cria o seguinte Departmentse Employeestabelas no banco de dados. Observe que o DepartmentIdna Employeestabela aceita NULL:

CREATE TABLE [dbo].[Departments] (
    [Id]   INT            IDENTITY (1, 1) NOT NULL,
    [Name] NVARCHAR (MAX) NOT NULL,
    CONSTRAINT [PK_Departments] PRIMARY KEY CLUSTERED ([Id] ASC)
);

CREATE TABLE [dbo].[Employees] (
    [Id]           INT            IDENTITY (1, 1) NOT NULL,
    [FirstName]    NVARCHAR (MAX) NOT NULL,
    [LastName]     NVARCHAR (MAX) NOT NULL,
    [JoinedDate]   DATETIME2 (7)  NOT NULL,
    [DepartmentId] INT            NULL,
    CONSTRAINT [PK_Employees] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_Employees_Departments_DepartmentId] FOREIGN KEY ([DepartmentId]) REFERENCES [dbo].[Departments] ([Id])
);


GO
CREATE NONCLUSTERED INDEX [IX_Employees_DepartmentId]
    ON [dbo].[Employees]([DepartmentId] ASC);

Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Resumo

  • O EF Core usa convenções para inferir os relacionamentos um-para-muitos entre as classes do modelo e criar as tabelas correspondentes no banco de dados.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *