Atualização do EF Core

Resumo : neste tutorial, você aprenderá várias maneiras de atualizar dados em tabelas de banco de dados no EF Core.

Configurando um projeto de exemplo

Primeiro, baixe o projeto de exemplo de RH:

Baixe o projeto de amostra do EF Core HR

Segundo, execute o comando Add-Migration no Package Manager Console (PMC) para criar uma nova migração:

Add-Migration InitialLinguagem de código:  C#  ( cs )

Terceiro, execute o comando Update-Database no PMC para criar um novo banco de dados e tabelas de RH no SQL Server local:

Update-DatabaseLinguagem de código:  C#  ( cs )

Executando uma atualização simples

Começaremos com a Departmententidade:

Vamos começar inserindo um novo departamento na Departmentstabela criando uma nova Departmententidade, adicionando-a ao DbSet<Department>e chamando o SaveChanges()método do HRContext:

using HR;

using var context = new HRContext();

var department = new Department() { Name = "Sales" };

context.Departments.Add(department);
context.SaveChanges();Linguagem de código:  C#  ( cs )

O EF Core irá inserir uma linha na Departmentstabela com id 1.

Para atualizar uma entidade, siga estas etapas:

  • Primeiro, obtenha a entidade consultando-a no banco de dados.
  • Em segundo lugar, faça alterações na entidade.
  • Terceiro, chame o SaveChanges()método de DbContextpara propagar as alterações no banco de dados.

Por exemplo, o seguinte altera o nome do Salesdepartamento com Id 1para Sales Force:

using HR;

using var context = new HRContext();

// get the department by Id
var department = context.Departments.Find(1);

if (department != null)
{
    // make changes to the department
    department.Name = "Sales Force";

    // update the changes
    context.SaveChanges();
}Linguagem de código:  C#  ( cs )

Observe que HRContextestende DbContexte define DbSetcomo Departmentscom o type DbSet<Department>.

Como funciona.

Primeiro, encontre o departamento com Id 1 usando o Find()método:

var department = context.Departments.Find(1);Linguagem de código:  C#  ( cs )

O EF Core executa uma SELECTinstrução SQL para localizar o departamento por Id:

-- [Parameters = [@__p_0 = '1' ], CommandType = 'Text', CommandTimeout = '30' ] 
SELECT 
  TOP(1) [d].[Id], 
  [d].[Name] 
FROM 
  [Departments] AS [d] 
WHERE 
  [d].[Id] = @__p_0Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Segundo, altere o nome do departamento para Sales Force:

department.Name = "Sales Force";Linguagem de código:  C#  ( cs )

Terceiro, salve as alterações no banco de dados chamando o Update()método de HRContext:

context.SaveChanges();Linguagem de código:  C#  ( cs )

O EF Core executa a UPDATEinstrução SQL para atualizar a Departmentstabela:

-- [Parameters=[@p1='1', @p0='Sales Force' (Nullable = false) (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET COCOUNT ON;

UPDATE 
  [Departments] 
SET 
  [Name] = @p0 
OUTPUT 1 
WHERE 
  [Id] = @p1;Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Se você visualizar a Departmentstabela, verá que o nome foi atualizado com sucesso:

Id          Name
----------- --------------------
1           Sales ForceLinguagem de código:  texto simples  ( texto simples )

Atualizando entidade com ID

Se você souber o ID da entidade, poderá atualizá-lo especificando o ID e os novos valores para as propriedades que deseja alterar. Por exemplo:

using HR;

using var context = new HRContext();

// Update the name of department
// with Id 1 to Sales
var department = new Department()
{
    Id = 1,
    Name = "Sales",
};

context.Update(department);
context.SaveChanges();Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, crie um novo Departmentobjeto especificando o Id 1 e o novo valor da Namepropriedade:

var department = new Department()
{
    Id = 1,
    Name = "Sales",
};Linguagem de código:  C#  ( cs )

Segundo, chame o Update()método de DbContextpara atualizar a entidade:

context.Update(department);Linguagem de código:  C#  ( cs )

Terceiro, chame o SaveChanges()para aplicar as alterações ao banco de dados:

context.SaveChanges();Linguagem de código:  C#  ( cs )

Neste exemplo, o EF Core só precisa executar uma UPDATEinstrução:

 -- [Parameters=[@p1='1', @p0='Sales' (Nullable = false) (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;

UPDATE [Departments] SET [Name] = @p0
OUTPUT 1
WHERE [Id] = @p1;Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Observe que se o Id for inválido, o EF Core não conseguirá encontrar o registro para atualização. Nesse caso, o EF Core gerará uma exceção como no exemplo a seguir:

using HR;

using var context = new HRContext();


var department = new Department()
{
    Id = 10, // Invalid Id
    Name = "Sales",
}; 

context.Update(department);
context.SaveChanges(); // -> ExceptionLinguagem de código:  C#  ( cs )

Atualizando em um relacionamento um-para-muitos

O programa a seguir adiciona um novo funcionário à Employeesmesa e um departamento à Departmentsmesa:

using HR;

using var context = new HRContext();

var department = new Department() { Name = "Marketing" };
var employee = new Employee()
{
    FirstName = "John",
    LastName = "Doe",
    Salary = 120_000,
    JoinedDate = new DateTime(2023, 5, 1),
    Department = department
};

context.Add(employee);
context.SaveChanges();Linguagem de código:  C#  ( cs )

O seguinte mostra o funcionário (não todos os campos) na Employeestabela:

Id          FirstName       LastName        DepartmentId
----------- --------------- --------------- ------------
1           John            Doe             2Linguagem de código:  texto simples  ( texto simples )

E aqui está o conteúdo da Departmentstabela:

Id          Name
----------- ---------------
1           Sales
2           MarketingLinguagem de código:  texto simples  ( texto simples )

Para atualizar o departamento do funcionário de Marketingpara Sales, você pode alterar o DepartmentIdda Employeeentidade e chamar o SaveChanges()método:

using HR;

using var context = new HRContext();

var employee = context.Employees.Find(1);

if(employee != null)
{
    employee.DepartmentId = 2;
    context.SaveChanges();
}Linguagem de código:  C#  ( cs )

Depois de executar o programa, você verá que o arquivo DepartmentIdestá atualizado:

Id          FirstName       LastName        DepartmentId
----------- --------------- --------------- ------------
1           John            Doe             2Linguagem de código:  texto simples  ( texto simples )

Como alternativa, você pode alterar a Departmentpropriedade da entidade funcionário para outro departamento e chamar o método SaveChanges().

O exemplo a seguir altera o departamento de John Doevolta para Sales:

using HR;

using var context = new HRContext();

// find the employee with id 1
var employee = context.Employees.Find(1);

if (employee != null)
{
    // find the Sales department
    var department = context.Departments
                            .Where(d => d.Name == "Sales")
                            .FirstOrDefault();

    if (department != null)
    {
        employee.Department = department;
        context.SaveChanges();
    }

}Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, encontre o funcionário com id 1:

var employee = context.Employees.Find(1);Linguagem de código:  C#  ( cs )

O EF Core executa uma SELECTinstrução para localizar o funcionário por id:

--  [Parameters=[@__p_0='1'], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [e].[Id], [e].[DepartmentId], [e].[FirstName], [e].[JoinedDate], [e].[LastName], [e].[Salary]
FROM [Employees] AS [e]
WHERE [e].[Id] = @__p_0Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Segundo, encontre o departamento pelo nome com o valor "Sales"e obtenha o primeiro:


var department = context.Departments
                        .Where(d => d.Name == "Sales")
                        .FirstOrDefault();Linguagem de código:  C#  ( cs )
-- [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [d].[Id], [d].[Name]
FROM [Departments] AS [d]
WHERE [d].[Name] = N'Sales'Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Terceiro, atualize o departamento do funcionário e ligue SaveChanges()para aplicar a alteração ao banco de dados:

employee.Department = department;
context.SaveChanges();Linguagem de código:  C#  ( cs )

O EF Core executará a seguinte UPDATEinstrução:

-- [Parameters=[@p1='1', @p0='1'], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;

UPDATE [Employees] SET [DepartmentId] = @p0
OUTPUT 1
WHERE [Id] = @p1;Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Atualizando em um relacionamento um-para-um

O exemplo a seguir mostra como adicionar um perfil a um funcionário:

using HR;

using var context = new HRContext();

// find the employee with id 1
var employee = context.Employees.Find(1);

if (employee != null)
{
    // create a profile for the employee
    employee.Profile = new EmployeeProfile()
    {
        Phone = "(408)-111-2222",
        Email = "[email protected]"
    };

    context.SaveChanges();
}Linguagem de código:  C#  ( cs )

O EF Core insere uma linha na EmployeeProfilestabela e define o valor de EmployeeIdcomo o valor do Id do funcionário:

Id          Phone                Email                EmployeeId
----------- -------------------- -------------------- -----------
1           (408)-111-2222       [email protected]    1Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Para atualizar o telefone do funcionário, você pode consultar o perfil do funcionário, modificar o telefone e ligar SaveChanges()da seguinte forma:

using HR;
using Microsoft.EntityFrameworkCore;

using var context = new HRContext();

// find the employee with id 1
var employee = context.Employees
                    .Include(e => e.Profile)
                    .Where(e => e.Id == 1)
                    .FirstOrDefault();


if (employee is not null && employee.Profile is not null)
{
    employee.Profile.Phone = "(408)-555-5555";
    context.SaveChanges();
}Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, encontre o funcionário, incluindo o perfil, com id 1:

var employee = context.Employees
                    .Include(e => e.Profile)
                    .Where(e => e.Id == 1)
                    .FirstOrDefault();Linguagem de código:  C#  ( cs )
 -- [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [e].[Id], [e].[DepartmentId], [e].[FirstName], [e].[JoinedDate], [e].[LastName], [e].[Salary], [e0].[Id], [e0].[Email], [e0].[EmployeeId], [e0].[Phone]
FROM [Employees] AS [e]
LEFT JOIN [EmployeeProfiles] AS [e0] ON [e].[Id] = [e0].[EmployeeId]
WHERE [e].[Id] = 1Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Segundo, modifique o telefone e atualize o banco de dados:

employee.Profile.Phone = "(408)-555-5555";
context.SaveChanges();Linguagem de código:  C#  ( cs )
-- [Parameters=[@p1='1', @p0='(408)-555-5555' (Nullable = false) (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
UPDATE [EmployeeProfiles] SET [Phone] = @p0
OUTPUT 1
WHERE [Id] = @p1;Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Se você visualizar a EmployeeProfilestabela, verá que o telefone do funcionário está atualizado:

Id          Phone                Email                EmployeeId
----------- -------------------- -------------------- -----------
1           (408)-555-5555       [email protected]    1Linguagem de código:  texto simples  ( texto simples )

Atualizando em um relacionamento muitos para muitos

A seguir, adicione duas habilidades ao funcionário com id 1:

using HR;

using var context = new HRContext();
var employee = context.Employees.Find(1);

if (employee is not null)
{
    var skills = new List<Skill>()
    {
        new() { Title = "Sales Planning" },
        new() { Title = "Sales Strategy" }
    };

    foreach (var skill in skills)
    {
        employee.Skills.Add(skill);
    }

    context.SaveChanges();
}Linguagem de código:  C#  ( cs )

O EF Core irá inserir duas novas linhas na tabela Skills:

Id          Title
----------- --------------------
1           Sales Planning
2           Sales StrategyLinguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

E atribua-o ao funcionário com Id 1 inserindo duas linhas na EmployeeSkilltabela:

EmployeesId SkillsId
----------- -----------
1           1
1           2Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Veja a seguir como remover o "Sales Strategy"ID do funcionário 1 e adicionar uma nova habilidade "Market Trend Analysis"ao funcionário:

using HR;
using static System.Console;
using Microsoft.EntityFrameworkCore;

using var context = new HRContext();

// find employee with skills
var employee = context.Employees
                .Include(e => e.Skills)
                .Where(e => e.Id == 1)
                .FirstOrDefault();

if (employee is not null && employee.Skills.Count > 0)
{
    // remove the "Sales Strategy" skill
    var skill = employee.Skills.Find(s => s.Title == "Sales Strategy");
    if(skill is not null) 
    {
        employee.Skills.Remove(skill);
    }

    // add "Market Trend Analysis" skill
    employee.Skills.Add(new Skill() { Title = "Market Trend Analysis" });
}

context.SaveChanges();Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, encontre o funcionário com id 1 e também adquira as habilidades:

var employee = context.Employees
                .Include(e => e.Skills)
                .Where(e => e.Id == 1)
                .FirstOrDefault();Linguagem de código:  C#  ( cs )
-- [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [t].[Id], [t].[DepartmentId], [t].[FirstName], [t].[JoinedDate], [t].[LastName], [t].[Salary], [t0].[EmployeesId], [t0].[SkillsId], [t0].[Id], [t0].[Title]
FROM (
    SELECT TOP(1) [e].[Id], [e].[DepartmentId], [e].[FirstName], [e].[JoinedDate], [e].[LastName], [e].[Salary]
    FROM [Employees] AS [e]
    WHERE [e].[Id] = 1
) AS [t]
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 [t0] ON [t].[Id] = [t0].[EmployeesId]
ORDER BY [t].[Id], [t0].[EmployeesId], [t0].[SkillsId]Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Segundo, desassocie a habilidade do funcionário:

var skill = employee.Skills.Find(s => s.Title == "Sales Strategy");
if(skill is not null) 
{
    employee.Skills.Remove(skill);
}Linguagem de código:  C#  ( cs )
 -- [Parameters=[@p0='1', @p1='2', @p2='Market Trend Analysis' (Nullable = false) (Size = 4000)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [EmployeeSkill]
OUTPUT 1
WHERE [EmployeesId] = @p0 AND [SkillsId] = @p1;

INSERT INTO [Skills] ([Title])
OUTPUT INSERTED.[Id]
VALUES (@p2);Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Tabela de habilidades:

Id          Title
----------- -------------------------
1           Sales Planning
2           Sales Strategy
3           Market Trend AnalysisLinguagem de código:  texto simples  ( texto simples )

Terceiro, insira uma nova habilidade na Skillstabela e associe a nova habilidade ao funcionário:

employee.Skills.Add(new Skill() { Title = "Market Trend Analysis" });Linguagem de código:  C#  ( cs )
INSERT INTO [Skills] ([Title])
OUTPUT INSERTED.[Id]
VALUES (@p2);

-- [Parameters=[@p3='1', @p4='3'], CommandType='Text', CommandTimeout='30']
SET IMPLICIT_TRANSACTIONS OFF;
SET NOCOUNT ON;
INSERT INTO [EmployeeSkill] ([EmployeesId], [SkillsId])
VALUES (@p3, @p4);Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

EmployeeSkillmesa:

EmployeesId SkillsId
----------- -----------
1           1
1           3Linguagem de código:  texto simples  ( texto simples )

Resumo

  • Para atualizar uma entidade, obtenha sua instância do banco de dados, modifique-a e chame o SaveChanges()método para atualizar.

Deixe um comentário

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