DbContext e o ObjectContext – Não deixe seus dados em memória!

O DbContext e o ObjectContext são duas classes responsáveis por gerenciar e acompanhar alterações em instâncias de classes no modelo, estas classes também gerenciam a conexão e o contexto de transação das operações com o banco de dados.

É importante assegurar que qualquer recurso associado com estes objetos seja limpo da memória quando não mais necessários, pois ao longo de cada execução é mantido um CACHE das instâncias de objetos recuperadas nas consultas. Se mantivermos a instância de nosso contexto por muito tempo ativa, executando consultas atrás de consultas, corremos o risco de consumir mais memória do que o necessário.

Para resolver esta questão, tanto a classe DbContext quanto a classe ObjectContext implementam a interface IDisposable, que inclui o método Dispose(), responsável por eliminar recursos utilizados pela instância corrente que não sejam mais necessários.

Como boa prática, propõem-se que sempre sejam limpos da memória os recursos que não forem mais necessários, por isso é indicado a chamada ao método Dispose().

Para automatizar a execução do método Dispose(), e assim liberar recursos da memória, recomenda-se a utilização do bloco USING, que irá na primeira linha criar uma instância de uma classe que implemente a interface IDisposable e que no fim do bloco irá executar (de maneira implícita) o método Dispose(). O exemplo abaixo ilustra o uso do bloco USING.

using

Se a sua aplicação não faz uso do bloco USING, então execute o método Dispose() explicitamente ao fim de cada transação com o banco de dados, para assegurar a limpeza de memória das instâncias de objetos contidas no contexto e que não são mais necessárias.

Outra prática errada que me deparo de vez em quando é o uso de classes Singleton que encapsulam uma instância de um contexto de acesso a dados. Este erro é bastante grave, pois devidos as características de utilização da classe Singleton, esta instância do contexto de acesso a dados apenas será limpa da memória quando a aplicação for finalizada. Este é um cenário péssimo, pois a quantidade de registros mantidos em memória de forma desnecessária é muito grande, impedindo a execução ótima da aplicação.
Obrigado pela atenção!

[]s e até o próximo!

Por
Fernando Henrique Inocêncio Borba Ferreira
Microsoft Most Valuable Professional – Data Platform Development

Anúncios

12 Responses to DbContext e o ObjectContext – Não deixe seus dados em memória!

  1. andrey says:

    então se eu fosse criar uma classe generica, para interagir com DbContext , e esta classe tivesse métodos de Dispose() ela seria desta maneira:

    private DbContext _contexto = new DbContext();

    //aqui ficam métods para o CRUD

    private bool disposed = false; //verificar se DisposeAuxiliar() já foi chamado

    public void Dispose()
    {
    DisposeAuxiliar();
    GC.SuppressFinalize(this); //Suprimir finalizador
    }

    ~RepositorioEF() //Finalizador
    {
    DisposeAuxiliar();
    }

    private void DisposeAuxiliar()
    {
    if (!this.disposed)
    {
    if (_contexto != null)
    {
    _contexto.Dispose(); //Dispose do Contexto
    }
    }

    disposed = true;
    }

  2. andrey says:

    fernando so mais uma dúvida, quando realizamos consultas no banco com o auxilio do DbContext estas consultas ficam em cache não é? Quando o GC coleta o objeto com o qual estavamos realizando estas consultas na base, esse cache q não tiver sido limpo com o Dispose() será eliminado na coleta de lixo?

    • Olá Andrey,
      Existem diferentes tipos de Cache no EF, mas o Cache de entidades retornadas perdura até o Dispose da instância do seu contexto.

      Que tipo de cenário vc esta enfrentando?

      []s!

      • andrey says:

        cache de entidades. era só para saber se este cache perdura mesmo apos o GC ter recolhido o objeto do tipo DbContext?

      • Oi Andrey,
        Não perdura. Por isso sempre uso o bloco using.

        []s!

      • andrey says:

        blz. então não tem necessidade de chamar o Dispose do contexto no finalizador. obrigado

      • Oi Andrey,
        A necessidade de executar o dispose é evitar que vc trabalhe com dados desatualizados e o consumo exagerado de memória, deixando seu acesso a dados mais lentos.

        E o uso do cache de entidades esta relacionado com o acesso a entidades durante blocos de transaçōes.

        []s!

  3. Pingback: entity_framework_melhores_praticas_performance_desempenho | Fernando Henrique Ferreira

  4. Mmrosa says:

    Algumas respostas aqui estão erradas, supondo que pretende inserir vários dados usando a mesma transação, a forma como sugere utilizar o EF trará problemas, pois cada operação passa a ser atómica.

    A transação apenas é aberta no momento em que é invocado o apply changes, originando a execução de todos os statements sql necessários para sincronizar o contexto com o banco de dados, e no final fazendo commit, garantindo assim atomicidade num Set de operações.

    O contexto deverá ser inicializado no início do Set de operações a executar e fechado no final, podendo utilizar ou não o using para o efeito.

  5. Willian Santos says:

    Fernando, agora fiquei confuso, hehehe

    Estava dando uma olhada nesse artigo do Jon Gallant (http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext/) ele repassa algumas informações da equipe do EF, em que eles falam que não é necessário chamar o Dispose(), pois o garbage collector é que se responsabiliza de eliminar esse lixo.

    Oq vc acha dessa abordagem?

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: