Depois de muito tempo sem postar um artigo técnico (andei postando algumas dicas, mas nada muito relevante), resolvi escrever um hoje. Vamos ver o que sai!

Estou participando de um projeto na qual utilizamos o Entity Framework para criação ORM (ou MOR – Modelo Objeto Relacional) de acesso ao banco de dados. Durante o desenvolvimento o cliente nos informou que a string de conexão com o banco de produção nos seria passada apenas através de uma DLL. Ou seja, não teríamos uma string de conexão propriamente dita no arquivo .config, e sim apenas um “esboço” dela.

A Connection String com todos os parâmetros preenchidos fica na DLL, por isso, no arquivo de configuração fica uma constante {CONST_CONNECTIONSTRING} que será substituída pela ConnectionString real.

A DLL contém um método estático que retorna a string de conexão. Para simular, vamos imaginar uma ClassLibrary com uma classe parecida com essa:

public class ConnectionString
{
    public static string GetConnectionString()
    {
        return "Data Source=.;
                Initial Catalog=TESTEEF;
                Integrated Security=True;
                MultipleActiveResultSets=True";
    }
}

Quando vamos criar uma instância do ObjectContext do Entity Framework, temos um construtor que nos permite passar a string de conexão que desejamos utilizar. Mas nesse caso, temos parte da string de conexão no arquivo de configuração e outra parte em uma DLL. Para resolver isso, fiz um outro método estático que “junta” as duas coisas:

public static string GetCompleteConnectionString(string strConnectionName)
{
    string strConnectionString = string.Empty;

    try
    {
        strConnectionString =
            ConfigurationManager.ConnectionStrings[strConnectionName]
            .ConnectionString;
        // é necessário: using System.Configuration;
    }
    catch
    {
        strConnectionString = string.Empty;
    }

    if (string.IsNullOrEmpty(strConnectionString))
        throw new Exception("ConnectionString não encontrada.");

    return strConnectionString.Replace("{CONST_CONNECTIONSTRING}",
        ConnectionString.ConnectionString.GetConnectionString());
}

Agora, para criar o ObjectContext usando a Connection String correta, basta usar o construtor que permite passar a string como parâmetro.

using (Entidades e =
    new Entidades
        (GerenciarConnectionString.GetCompleteConnectionString("Entidades")))
{

}

Pronto, terminamos! Mas ainda tem um “porém”. Quando estava desenvolvendo pensei o seguinte: “Vou ter que passar a ConnectionString em todos os lugares onde crio uma instância do ObjectContext? E se em algum eu passar o nome da ConnectionString errado?”. Para resolver isso, criei um novo construtor para a classe que representa o ObjectContext na qual eu sempre pego a ConnectionString através do método GetCompleteConnectionString que mostrei acima. Isso só é possível pelo fato da classe que representa o ObjectContext ser partial.

A classe parcial com o novo construtor ficou assim:

public partial class Entidades : global::System.Data.Objects.ObjectContext
{
    public Entidades(bool bolBuscarConnectionStringCorreta) :
        base(GerenciarConnectionString.GetCompleteConnectionString("Entidades"),
        "Entidades")
    {
        if (!bolBuscarConnectionStringCorreta)
            throw new Exception("Este construtor permite apenas TRUE.");

        this.OnContextCreated();
    }
}

Feito isso, basta usar este novo construtor para a criação das instâncias do ObjectContext.

using (Entidades e = new Entidades(true))
{

}

É isso, galera! Espero que seja útil.

O código fonte pode ser baixado aqui.

Obrigado