Partilhar via


Configuração baseada em código

Observação

EF6 em diante apenas: os recursos, as APIs etc. discutidos nessa página foram introduzidos no Entity Framework 6. Se você estiver usando uma versão anterior, algumas ou todas as informações não se aplicarão.

A configuração de um aplicativo do Entity Framework pode ser especificada em um arquivo de configuração (app.config/web.config) ou por meio de código. Este último é conhecido como configuração baseada em código.

A configuração em um arquivo de configuração é descrita em um artigo separado. O arquivo de configuração tem precedência sobre a configuração baseada em código. Em outras palavras, se uma opção de configuração for definida no código e no arquivo de configuração, a configuração no arquivo de configuração será a usada.

Usando DbConfiguration

A configuração baseada em código no EF6 e posterior é obtida com a criação de uma subclasse de System.Data.Entity.Config.DbConfiguration. As diretrizes a seguir devem ser seguidas ao criar subclasses de DbConfiguration:

  • Crie apenas uma classe DbConfiguration para seu aplicativo. Essa classe especifica as configurações de todo o domínio do aplicativo.
  • Coloque sua classe DbConfiguration no mesmo assembly que sua classe DbContext. (Consulte a seção Movendo DbConfiguration se você quiser alterar isso).
  • Dê à sua classe DbConfiguration um construtor público sem parâmetros.
  • Defina as opções de configuração chamando métodos DbConfiguration protegidos de dentro desse construtor.

Seguir essas diretrizes permite que o EF descubra e use sua configuração automaticamente por meio de ferramentas que precisam acessar seu modelo e quando seu aplicativo é executado.

Exemplo

Uma classe derivada de DbConfiguration pode ter esta aparência:

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.SqlServer;

namespace MyNamespace
{
    public class MyConfiguration : DbConfiguration
    {
        public MyConfiguration()
        {
            SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
            SetDefaultConnectionFactory(new LocalDbConnectionFactory("mssqllocaldb"));
        }
    }
}

Essa classe configura o EF para usar a estratégia de execução do SQL Azure – para repetir automaticamente operações de banco de dados com falha – e usar o BD Local para bancos de dados criados por convenção a partir do Code First.

Movendo DbConfiguration

Há casos em que não é possível colocar sua classe DbConfiguration no mesmo assembly que sua classe DbContext. Por exemplo, você pode ter duas classes DbContext cada em assemblies diferentes. Há duas opções para lidar com isso.

A primeira opção é usar o arquivo de configuração para especificar a instância DbConfiguration a ser usada. Para fazer isso, defina o atributo codeConfigurationType da seção entityFramework. Por exemplo:

<entityFramework codeConfigurationType="MyNamespace.MyDbConfiguration, MyAssembly">
    ...Your EF config...
</entityFramework>

O valor de codeConfigurationType deve ser o nome qualificado do assembly e do namespace da sua classe DbConfiguration.

A segunda opção é colocar DbConfigurationTypeAttribute em sua classe de contexto. Por exemplo:

[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext
{
}

O valor passado para o atributo pode ser o tipo DbConfiguration, conforme mostrado acima, ou a cadeia de caracteres do nome de tipo qualificado do assembly e namespace. Por exemplo:

[DbConfigurationType("MyNamespace.MyDbConfiguration, MyAssembly")]
public class MyContextContext : DbContext
{
}

Configurando DbConfiguration explicitamente

Há algumas situações em que a configuração pode ser necessária antes de qualquer tipo DbContext ser usado. Alguns exemplos disso incluem:

  • Usar DbModelBuilder para criar um modelo sem um contexto
  • Usando algum outro código de estrutura/utilitário que utiliza um DbContext em que esse contexto é usado antes que o contexto do aplicativo seja usado

Nessas situações, o EF não consegue descobrir a configuração automaticamente e, em vez disso, você deve executar um dos seguintes procedimentos:

  • Defina o tipo DbConfiguration no arquivo de configuração, conforme descrito na seção Movendo DbConfiguration acima
  • Chame o método estático DbConfiguration.SetConfiguration durante a inicialização do aplicativo

Substituindo DbConfiguration

Há algumas situações em que você precisa substituir o conjunto de configuração no DbConfiguration. Isso normalmente não é feito por desenvolvedores de aplicativos, mas sim por provedores e plug-ins de terceiros que não podem usar uma classe DbConfiguration derivada.

Para isso, o EntityFramework permite que seja registrado um manipulador de eventos que pode modificar a configuração existente pouco antes de ser bloqueado. Ele também fornece um método de açúcar especificamente para substituir qualquer serviço retornado pelo localizador de serviço EF. É assim que se destina a ser usado:

  • Na inicialização do aplicativo (antes do EF ser usado), o plug-in ou provedor deve registrar o método do manipulador de eventos para esse evento. (Observe que isso deve acontecer antes que o aplicativo use o EF.)
  • O manipulador de eventos faz uma chamada para ReplaceService para cada serviço que precisa ser substituído.

Por exemplo, para substituir IDbConnectionFactory e DbProviderService você registraria um manipulador mais ou menos assim:

DbConfiguration.Loaded += (_, a) =>
   {
       a.ReplaceService<DbProviderServices>((s, k) => new MyProviderServices(s));
       a.ReplaceService<IDbConnectionFactory>((s, k) => new MyConnectionFactory(s));
   };

No código acima, MyProviderServices e MyConnectionFactory representam suas implementações do serviço.

Você também pode adicionar manipuladores de dependência adicionais para obter o mesmo efeito.

Observe que você também pode encapsular DbProviderFactory dessa forma, mas fazer isso afetará apenas o EF e não os usos do DbProviderFactory fora do EF. Por essa razão, você provavelmente vai querer continuar a encapsular DbProviderFactory como fez antes.

Você também deve levar em conta os serviços executados externamente para seu aplicativo, por exemplo, ao executar migrações do Console do Gerenciador de Pacotes. Quando você executar a migração do console, ele tentará localizar seu DbConfiguration. No entanto, se ele obterá ou não o serviço encapsulado depende de onde o manipulador de eventos foi registrado. Se ele estiver registrado como parte da construção do seu DbConfiguration, então o código deverá ser executado e o serviço deverá ser encapsulado. Normalmente, não é o que ocorre e isso significa que as ferramentas não receberão o serviço encapsulado.