EF Core 2.x - Soft Delete (Exclusão suave)
Hoje vou apresentar o recurso Soft Delete ou exclusão suave do EF Core 2.1. |
O recurso Soft-Delete ou exclusão suave é bem simples: significa que ao invés de excluir os registros do banco de dados, nós vamos apenas 'marcar' os registros como excluídos. Para fazer isso geralmente criamos uma coluna chamada IsDeleted que recebe o valor true para indicar que o registro foi marcado para exclusão.
Assim, para implementar o Soft Delete temos que :
Uma forma bem simples de fazer isso é criar uma coluna IsDeleted, e, toda vez que um registro tiver que ser excluído, na verdade atualizamos esta coluna com o valor true.
Vamos ver isso funcionando na prática.
Vamos supor que já temos um banco de dados chamado ABDemoDB e a tabela Alunos com a seguinte estrutura:
Observe a coluna IsDeleted definida com o tipo bit que vai receber os valores true(1) ou false(0).
Abaixo vemos o script SQL para criar a tabela Alunos com a restrição definida :
USE [ABDemoDB] GO CREATE TABLE [dbo].[Alunos]( [AlunoId] [int] IDENTITY(1,1) NOT NULL, [Nome] [nvarchar](100) NOT NULL, [Curso] [nvarchar](50) NOT NULL, [Nota] [char](1) NOT NULL, [IsDeleted] [bit] NOT NULL, CONSTRAINT [PK_Alunos] PRIMARY KEY CLUSTERED ([AlunoId] ASC) ); |
O valor padrão para a coluna IsDeleted é 0, ou seja, false : (1 é o valor para true)
Criando o projeto no VS 2017 Community
Abra o VS 2017 Community e crie um novo projeto .NET Core do tipo Console App(.NET Core) chamado EFCore_SofDelete.
Inclua no projeto a referência para o Microsoft.EntityFrameworkCore.SqlServer :
Observe que estou usando a versão 2.21, que é a versão mais estável, mas podemos usar a versão 2.1 ou superior.
Crie no projeto a pasta Model e nesta pasta inclua duas classes:
1- Aluno
namespace EFCore_ConvertValue.Model
{
public class Aluno
{
public int AlunoId { get; set; }
public string Nome { get; set; }
public string Curso { get; set; }
public char Nota { get; set; }
public bool IsDeleted {get; set; }
}
}
|
Note que definimos uma propriedade IsDeleted do tipo bool que vai receber os valores true e false;
2- AppDbContext
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace EFCore_SoftDelete.Model
{
public class AppDbContext : DbContext
{
public DbSet<Aluno> Alunos { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Data Source=Macoratti;Initial Catalog=ABDemoDB;Integrated Security=True");
}
public override int SaveChanges()
{
//Soft-Delete
foreach (var item in ChangeTracker.Entries()
.Where(e => e.State == EntityState.Deleted &&
e.Metadata.GetProperties().Any(x => x.Name == "IsDeleted")))
{
item.State = EntityState.Unchanged;
item.CurrentValues["IsDeleted"] = true;
}
return base.SaveChanges();
}
}
}
|
Neste código sobrescrevemos o método SaveChanges na classe de contexto que percorre o ChangeTracker verificando se o estado das entidade é Deleted, e, se o nome da propriedade é "IsDeleted", neste caso definimos o estado da entidade como Unchanged e atribuimos o valor true para a coluna IsDeleted.
Agora, no arquivo Program.cs inclua o código abaixo:
using EFCore_SoftDelete.Model;
using static System.Console;
namespace EFCore_SoftDelete
{
class Program
{
static void Main(string[] args)
{
using (var contexto = new AppDbContext())
{
DeletaAluno(contexto);
ListaAluno(contexto);
ReadLine();
}
}
private static void ListaAluno(AppDbContext contexto)
{
foreach (var aluno in contexto.Alunos)
{
WriteLine($"{aluno.Nome,10} {aluno.Curso,-15} {aluno.Nota,-10}");
}
}
private static void DeletaAluno(AppDbContext contexto)
{
var aluno = contexto.Alunos.Find(1);
contexto.Remove(aluno);
contexto.SaveChanges();
}
}
}
|
No código acima temos o método DeletaAluno() que vai localizar o aluno com Id igual a 1(Find(1)), e, a seguir, vai remover a entidade usando o método Remove(); para efetivar a remoção emitimos um SaveChanges.
Aqui na verdade vai entrar em cena o Soft Delete que implementamos, e o registro não será excluído, mas o valor da coluna IsDelete vai ser alterado para true ou 1.
Executando projeto e verificando a tabela Alunos no banco de dados temos o seguinte:
Note que o registro para AlunoId igual a 1 teve o valor da coluna IsDeleted alterado para 1.
Mas para não exibir os registros marcados para deleção temos que alterar a consulta.
Uma forma bem simples de fazer isso é usar o recurso Global Query Filter que eu já apresentei neste artigo: Entity Framework Core - Aplicando Global Query Filters
No nosso exemplo basta alterar o arquivo de contexto incluindo o código abaixo no método OnModelCreating:
....
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Aluno>()
.HasQueryFilter(aluno => EF.Property<bool>(aluno, "IsDeleted") == false);
}
...
|
Agora ao executar o projeto vamos ver a lista de alunos exibindo apenas os alunos que não estão marcados para exclusão:
Pegue o código completo do projeto aqui: EFCore_SoftDelete.zip
"Falou-lhes,
pois, Jesus outra vez, dizendo: Eu sou a luz do mundo; quem me segue não andará
em trevas, mas terá a luz da vida."
João
8:12
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
EF Core - Iniciando com o Entity Framework Core - Macoratti
EF Core - Usando a abordagem DataBase First - Criando - Macoratti
EF Core - Apresentando o EF Core Power Tools - Macoratti
EF Core 2.0 - Scaffolding DbContext e Models usando CLI - Macoratti
ASP .NET Core - CRUD usando Blazor e Entity Framework ... - Macoratti
Curso Entity Framework Core 2.0 - Vídeo Aulas - Macoratti