Trabalhar com o DbContext

Para usar o Entity Framework para consultar, inserir, atualizar e eliminar dados usando objetos .NET, primeiro precisa de criar um Modelo que mapeie as entidades e relações definidas no seu modelo para tabelas numa base de dados.

Depois de ter um modelo, a classe principal com que a sua aplicação interage é System.Data.Entity.DbContext (frequentemente referida como classe de contexto). Pode usar um DbContext associado a um modelo para:

  • Escrever e executar consultas
  • Materializar resultados de consulta como objetos de entidade
  • Registar as alterações feitas a esses objetos
  • Persistir alterações de objetos na base de dados
  • Vincule objetos na memória aos controlos da interface de utilizador

Esta página dá algumas orientações sobre como gerir a classe de contexto.

Definição de uma classe derivada de DbContext

A forma recomendada de trabalhar com o contexto é definir uma classe que derive do DbContext e exponha propriedades do DbSet que representam coleções das entidades especificadas no contexto. Se estiver a trabalhar com o EF Designer, o contexto será gerado por si. Se estiveres a trabalhar com o Code First, normalmente vais escrever o contexto tu próprio.

public class ProductContext : DbContext
{
    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
}

Uma vez tendo um contexto, deves consultar, adicionar (usando os métodos Add ou Attach) ou remover (usando Remove) entidades no contexto através dessas propriedades. Aceder a uma DbSet propriedade num objeto de contexto representa uma consulta inicial que devolve todas as entidades do tipo especificado. Note que apenas aceder a uma propriedade não executará a consulta. Uma consulta é executada quando:

  • É enumerado por uma foreach instrução (C#) ou For Each (Visual Basic).
  • É enumerado por uma operação de coleção como ToArray, ToDictionary, ou ToList.
  • Operadores LINQ como First ou Any são especificados na parte mais externa da consulta.
  • Um dos seguintes métodos é chamado: o Load método de extensão, DbEntityEntry.Reload, Database.ExecuteSqlCommand, e DbSet<T>.Find, se uma entidade com a chave especificada não for encontrada já carregada no contexto.

Lifetime

A vida útil do contexto começa quando a instância é criada e termina quando a instância é descartada ou recolhida no lixo. Use using se desejar que todos os recursos controlados pelo contexto sejam libertados no final do bloco. Quando usa using, o compilador cria automaticamente um bloco try/finally e chama dispose no bloco finally.

public void UseProducts()
{
    using (var context = new ProductContext())
    {     
        // Perform data access using the context
    }
}

Aqui estão algumas orientações gerais ao decidir o tempo de vida do contexto:

  • Ao trabalhar com aplicações Web, utilize uma instância de contexto por pedido.
  • Ao trabalhar com Windows Presentation Foundation (WPF) ou Windows Forms, use uma instância de contexto por formulário. Isto permite-te usar a funcionalidade de acompanhamento de alterações que o contexto fornece.
  • Se a instância de contexto for criada por um contentor de injeção de dependência, normalmente é responsabilidade do contentor eliminar o contexto.
  • Se o contexto for criado em código de aplicação, lembre-se de eliminar o contexto quando já não for necessário.
  • Ao trabalhar com contexto de longa duração, considere o seguinte:
    • À medida que carregas mais objetos e as suas referências na memória, o consumo de memória do contexto pode aumentar rapidamente. Isto pode causar problemas de desempenho.
    • O contexto não é seguro para threads, por isso não deve ser partilhado entre múltiplas threads que trabalham nele em simultâneo.
    • Se uma exceção fizer com que o contexto fique num estado irrecuperável, toda a aplicação pode terminar.
    • As probabilidades de se depararem com problemas relacionados com a concorrência aumentam à medida que o intervalo entre o momento em que os dados são consultados e atualizados aumenta.

Connections

Por padrão, o contexto gere as ligações com a base de dados. O contexto abre e fecha ligações conforme necessário. Por exemplo, o contexto abre uma ligação para executar uma consulta e depois fecha a ligação quando todos os conjuntos de resultados já foram processados.

Há casos em que queres ter mais controlo sobre quando a ligação abre e fecha. Por exemplo, ao trabalhar com SQL Server Compact, é frequentemente recomendado manter uma ligação aberta separada à base de dados durante toda a vida útil da aplicação para melhorar o desempenho. Pode gerir este processo manualmente utilizando a Connection propriedade.