Entity Framework - DetectChanges

Conforme prometido no post anterior, vou resumir o funcionamento do método DetectChanges do EntityFramework. Para isso, vamos tomar como exemplo a classe de uma entidade Aluno conforme abaixo:

public class Aluno
{
    public int AlunoId { get; set; }
    public string Nome { get; set; }
    public int TurmaId { get; set; }
    public virtual Turma Turma { get; set; }    
}

Não há nenhum trecho no código acima que notifique e mantenha o controle de alteração dessa entidade.

Quando executamos uma alteração das propriedades de Aluno usando o seguinte código

using (var context = new EntityContext())
{
    var aluno = context.Alunos.Single(a=>a.Nome == "Maria Luiza");
    aluno.Nome = "Ana Maria";
    context.SaveChanges();
}

O EF sabe que precisará enviar um comando de "update" ao banco de dados fazendo um snapshot das propriedades no momento em que o o objeto é obtido do banco de dados e comparando com seu estado final na execução do método SaveChanges().

No exemplo, modificamos a propriedade Nome, o método DetectChanges foi chamado pelo SaveChanges para escanear e comparar as propriedades para posteriormente executar o update.

O método DetectChanges também é responsável por fazer outras verificações importantes. Vejamos o exemplo de relacionamento abaixo:
Banco-De-Dados-Aluno-Turma

Maria Luiza faz parte da Turma de ASP NET MVC5. Vamos supor que eventualmente haja uma tentativa de alteração indevida da propriedade TurmaId na entidade Aluno:

using (var context = new EntityContext())
{
    try
    {
        var aluno = context.Alunos.Single(a=>a.Nome == "Maria Luiza");
        aluno.TurmaId = 3;  // FK - TurmaId inexistente
        context.SaveChanges();
    }
    catch (Exception erro)
    {
        Console.WriteLine(erro.Message);
    }
}

O DetectChanges irá retornar uma exceção, pois uma de suas funções é verificar a existência da nova FK.
Banco-De-Dados-Aluno-Turma-Exception

- O que aconteceria se eu desabilitasse o DetectChanges ?

Vamos testar setando false no método AutoDetectChangesEnabled:

using (var context = new EntityContext())
{
    try
    {
        context.Configuration.AutoDetectChangesEnabled = false; // Desabilitando AutoDetectChanges
        var aluno = context.Alunos.Single(a=>a.Nome == "Maria Luiza");
        aluno.Nome = "Ana Maria";
        aluno.TurmaId = 3;
        Console.WriteLine(context.Entry(aluno).State);
        context.SaveChanges();
    }
    catch (Exception erro)
    {
        Console.WriteLine(erro.Message);
    }
}

Executando o código acima, o EF não atualizou a entidade com um novo nome pois ele não conhecia as propriedades modificadas e simplesmente não fez nada. Nem ao menos gerou uma exceção em relação à propriedade inexistente TurmaId. Vejam que o estado da entidade aluno foi retornado como "Unchanged".
Banco-De-Dados-Aluno-Turma-Unchanged

Enfim, não é recomendável desabilitar o AutoDetectChangesEnabled. No meu post anterior, desativei pra ganhar performance em um teste onde eu executava um insert de 10.000 novos registros numa tabela simples. Especificamente nesse contexto de teste, torná-lo off, resultou em uma expressiva redução do tempo que era de 40 segundos em média para aproximadamente 3 segundos.

Sugiro a leitura do blog do Arthur Vickers, desenvolvedor que atua no time de desenvolvimento do Entity Framework, que escreveu uma série de 4 posts sobre o tema - Link: Secrets of DetectChanges Part 1: What does DetectChanges do?

Até a próxima!
Abs

15 thoughts on “Entity Framework - DetectChanges

  1. I love what you guys are up too. This kind of clever work and reporting!
    Keep up the excellent works guys I’ve you guys to our blogroll.

  2. Valeu Bruno! Existem algumas maneiras de tunar o EF. Vou tentar criar alguns cenários e testar desempenho antes e depois de aplicar o tunning. Irei postar em seguida.

    Obrigado!

  3. Excelente dica, é muito importante sabermos usar o entity, pois já vi muita gente usando ele da maneira errada e dizendo que a culpa no Entity pois ele é "lento".

    Post mais dicas sobre Entity Framework.

Leave a Reply

Your email address will not be published. Required fields are marked *

This blog is kept spam free by WP-SpamFree.