Entity Framework Core - TrackGraph e Entidades desconectadas
Neste artigo veremos como tratar dados complexos em cenários desconectados usando o método TrackGraph do EF Core. |
O EF
Core fornece os métodos Add, Attach e Update
que podem ser utilizados para o grafo de entidades. Embora estes métodos
funcionem perfeitamente em cenários conectados, é possível que se queira
trabalhar muitas vezes em modo desconectado e seguir todo o gráfico do objeto.
Para isso podemos usar o método ChangeTracker.TrackGraph.
Nota: O
ChangeTracker altera de forma automática o
EntityState de cada entidade em um cenário conectado.
O método TrackGraph pode ser utilizado para
rastrear um gráfico de entidade inteiro, e está disponível como parte do
namespace Microsoft.EntityFrameworkCore.ChangeTracking
e foi concebido para funcionar em cenários desconectados. Enquanto as entidades
são recuperadas utilizando uma instância do contexto de dados, as alterações a
essas entidades são armazenadas de forma persistente utilizando outra instância
do contexto de dados.
Para acompanhar as alterações a uma entidade, o EF Core tira partido de uma propriedade chamada State que está ligada a todas as entidades rastreadas. Esta propriedade é um enumeração do tipo EntityState. Os seguintes métodos, quando utilizados, alteram o EntityState de uma entidade no gráfico da entidade :
Attach(), Entry(), Add(), Update() e Remove()
O EF Core é hábil em gerar o SQL a ser executado com base
no estado atual de um gráfo de entidades e a funcionalidade
de rastreamento das entidades ou changing tracking funciona muito bem.
A seguir temos um exemplo que ilustra este recurso:
using (var context = new DemoDataContext())
{
var autor = context.Autores.Single(a => a.Id == 1);
autor.Nome = "José";
autor.Sobrenome = "Queiroz";
context.SaveChanges();
}
|
Neste trecho de código a entidade autor é
recuperada dentro do bloco using e o EF Core
começa a rastrear esta entidade imediatamente após a instância da entidade ser
criada.
Quando o método
SaveChanges é chamado na instância de contexto de
dados, o EF Core verifica se foram feitas quaisquer alterações na entidade que
está a ser persistida e gera a instrução SQL, conforme apropriado. No nosso
exemplo, as duas propriedades Nome e Sobrenome
foram atualizadas.
Ao trabalhar no modo desconectado, seria necessário avisar explicitamente o
contexto de que a entidade foi modificada. Isto pode ser feito de várias
maneiras diferentes. Abaixo destacamos 3 formas de fazer isso:
Definir a propriedade EntityState
Usar o método DbContext.Update
Usar o método DbContext.Attach
1 - Definindo a propriedade EntityState
O estado de uma entidade determina como as entidades rastreadas serão processadas quando o método SaveChanges for chamado. Uma entidade pode estar em qualquer um dos seguintes estados:
Added, Unchanged, Modified e Deleted
O seguinte trecho de código ilustra como a propriedade EntityState pode ser definida como Modified:
public void Save(Artigo artigo)
{
context.Entry(artigo).State = EntityState.Modified;
context.SaveChanges();
}
|
Note que esta
abordagem permitirá o rastreio apenas para a entidade Artigo. As entidades
relacionadas da entidade Artigo não serão rastreadas.
2 - Usando o método de Update na instância do contexto
dos dados
O código a ser ilustra o uso do método Update :
public void Save(Artigo artigo)
{
context.Update(artigo)
context.SaveChanges();
}
|
O método Update pode ser usado para uma entidade
enquanto o método UpdateRange pode ser usado para
várias entidades. A chamada ao método Update marca
a entidade rastreada como modified.
Usando o método Attach
Quando se chama o método Attach sobre uma entidade,
o estado da entidade e todas as outras entidades alcançáveis tornam-se
Unchanged (Inalterados).
Podemos definir
explicitamente a propriedade IsModified como
true para assegurar que o contexto está
ciente das propriedades da entidade que foram alteradas. O seguinte trecho de
código ilustra como isto pode ser alcançado.
var autor = new Autor {
Id = 1,
Nome = "José";
Sobrenome = "Queiroz";
};
context.Attach(autor);
context.Entry(autor).Property("Nome").IsModified = true;
context.Entry(autor).Property("Sobrenome").IsModified = true;
|
Neste código ambas as propriedades Nome e Sobrenome são modificadas e têm o seu estado definido como modified.
O EF Core dá suporte ao rastreamento de
entidades, e , com o método TrackGraph temos uma
maneira fácil de interagir com um gráfico de objetos que desejássemos que fossem
rastreados.
Podemos assim tirar partido do método
TrackGraph para acessar as entidades individuais
dentro de um gráfico de objetos e depois executar código personalizado contra
cada uma das entidades do gráfico.
Criando o projeto no VS 2019
Para ilustrar isso vamos criar uma aplicação Console do tipo NET Core usando o VS 2019 Community chamada EFCore_TrackGraph1.
A seguir selecione o Target Framework como .NET 5.0 (Current) conforme figura abaixo:
Clique em Create.
Vamos iniciar incluindo as referências aos seguintes pacotes do EF Core neste projeto:
Para incluir os pacotes use o menu Tools->..-> Manage Nuget Packages for Solution e na guia Browse selecione e instale os pacotes ou abra a janela Package Manager Console e digite o comando: install-package <nome-pacote>
A seguir vamos criar o seguinte modelo de entidades usadas no projeto:
1- Autor
public class Autor
{
public int Id { get; set; }
public string Nome { get; set; }
public Endereco Endereco { get; set; }
public List<Artigo> Artigos { get; set; }
}
|
2- Endereco
public class Endereco
{
public int Id { get; set; }
public string Local { get; set; }
public string Cidade { get; set; }
}
|
3- Artigo
public class Artigo
{
public int Id { get; set; } public string Titulo { get; set; } } |
Abaixo temos o diagrama de classes gerado no VS 2019 :
Agora vamos criar a classe de contexto AppDbContext
:
using Microsoft.EntityFrameworkCore; namespace EFCore_TrackGraph1.Data protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) public DbSet<Autor> Autores { get; set; } |
Com isso podemos usar o o método TrackGraph conforme mostrado a seguir:
using EFCore_TrackGraph1.Data; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic;
namespace EFCore_TrackGraph1 context.ChangeTracker.TrackGraph(autor, a => foreach (var entry in context.ChangeTracker.Entries()) |
Inicialmente estamos povoando as entidades com alguns
dados começando com a entidade Raiz que é o Autor.
A seguir estamos usando o método
TrackGraph para o autor, e, se uma entidade tiver uma chave, o estado da
entidade é marcado como "Unchanged"; Se uma
entidade não tiver uma chave associada, o estado da entidade é assinalado como "Added".
A propriedade IsKeySet obtém um valor que indica se aos valores-chave desta entidade foram atribuídos um valor.
Concluindo usamos um laço foreach para exibir o
nome da entidade e o estado das entidades que não têm uma chave.
Pegue o código do projeto aqui:
EFCore_TrackGraph1.zip
(sem as referências)
"A palavra de Cristo habite em vós
abundantemente, em toda a sabedoria, ensinando-vos e admoestando-vos uns aos
outros, com salmos, hinos e cânticos espirituais, cantando ao Senhor com graça
em vosso coração."
Colossenses 3:16
Referências:
EF Core - Iniciando com o Entity Framework Core -
EF Core - Usando a abordagem DataBase First - Criando uma aplicação console
EF Core - Dicas de desempenho
ASP .NET Core 5 - CRUD com EF Core 5 usando imagens