Desvendando o Entity Framework - A classe EntityConnection


Um dos benefícios de utilizar o Entity Framework é que ele remove a necessidade de escrever código para configurar a conexão com o banco de dados.

A partir do momento que uma string de conexão esta disponível para o Entity Framework, geralmente como parte do Entity ConnectionString, que é salva na seção ConnectionStrings, definida no arquivo configuração (web.config ou app.config), o Entity Framework irá automaticamente definir, abrir e fechar a conexão com o banco de dados para você.

Comparado com o código ADO .NET tradicional, onde você precisa instanciar, definir, e em muitos casos, explicitamente abrir uma conexão, instanciar e definir um comando, executar o comando e então explicitamente fechar a conexão, o Entity Framework, através do ObjectContext, cuida de todas essas tarefas para você em segundo plano.

Esta é uma vantagem que você terá em um cenário de consultas padrão, mas às vezes você vai querer ter um controle mais efetivo sobre como e quando as conexões estão sendo gerenciadas. Para estar apto a ter este controle vamos dar uma olhada em como o EntityConnection e o DbConnection se relacionam entre si; vamos ver também como forçar via código que eles trabalhem da maneira que você deseja quando o comportamento padrão não resolver o seu problema.

Nota: A classe EntityConnection contém uma referência ao Entity Data Model (EDM) e uma conexão com a fonte de dados; a classe DbConnection, do namespace System.Data.Common, representa uma conexão com um banco de dados.

EntityConnection versus Conexões de banco de dados

Uma EntityConnection não é uma conexão com um banco de dados. Embora você possa abrir e fechar uma EntityConnection, isso não significa que você esta abrindo e fechando uma conexão com um banco de dados. Se você usar o EntityClient diretamente ou deixar que os Object Services executem os seus comandos e consultas, a EntityConnection será apenas um caminho para a conexão com o banco de dados.

Nota: O provedor EntityClient usa os recursos de armazenamento específico das classes do ADO .NET Data Provider e o mapeamento para interagir com um modelo de entidades de dados e traduzir as operações realizadas no modelo conceitual em operações realizadas na fonte de dados física.

Uma EntityConnection é composto por 4 partes:

  1. MetaData - O ponteiro para os arquivos de metadados CSDL, MSL e SSDL;
  2. Provider Connection - a string de conexão com o banco de dados;
  3. Provider Name - O namespace do provedor do banco de dados;
  4. Name - O nome da string de conexão;

Você pode definir a EntityConnection declarativamente no arquivo de configuração (app.config ou web.config) . Abaixo temos um exemplo onde o nome da string de conexão e da string EntityConnection são definidos em um arquivo app.config:

<connectionStrings>
<add name="MacorattiEntities" 
    connectionString="metadata=res://*/MACModel.csdl|res://*/MACModel.ssdl|res://*/MACModel.msl;
    provider=System.Data.SqlClient;
    provider connection string='Data Source=.\SQLEXPRESS;Initial Catalog=Macoratti;Integrated Security=True;
                               MultipleActiveResultSets=True'" 
    providerName="System.Data.EntityClient"
 />
</connectionStrings>

Nota: Quando o assistente de configuração do Entity Framework cria esta string para você , ele substitui as aspas em torno da provider connection string com um caractere &quot, o qual é o enconding XML para aspas. No exemplo acima estamos usando a notação com aspas para facilitar a legibilidade.

Por padrão o ObjectContext irá usar a string de conexão a partir do arquivo de configuração que coincide o nome definido no EntityContainer do seu modelo.

Nota: Um EntityContainter, definido no CSDL, representa um container de entidade no EDM e pode se consideradoc como um agrupamento lógico de conjuntos de entidades e associações. Ele controla o escopo das entidades e associações no modelo de objetos definido.

A string de conexão do banco de dados que esta embutida na string EntityConnection é passada adiante para o provedor do banco de dados que eventualmente realiza a conexão com o banco de dados.

Construindo strings EntityConnection

 A EntityConnection é uma classe que fica no namespace EntityClient; veremos a seguir como construir strings EntityConnection usando o nome da string de conexão no arquivo de configuração que será passado como um parâmetro no construtor EntityConnection; neste caso a conexão será criada a partir dos detalhes fornecidos pela string de conexão:

Using conn As EntityConnection= New EntityConnection("name=MacorattiEntities")

Você também pode usar o método anterior para selecionar de forma explícita uma string de conexão particular a partir do arquivo de configuração quando instanciar um ObjectContext:

Dim context= New MacorattiEntities("name=OutraConnectionString")

Quando você usa  este construtor para um EntityConnection ou ObjectContext , a ConnectionString não é lida na sua totalidade. Para ler a string de conexão completa a partir do arquivo de configuração você pode usar um dos métodos de leitura de dados a partir do arquivo de configuração como System.Configuration.ConfigurationManager.

Usando a classe EntityConnectionStringBuilder

Você pode também programar via código uma EntityConnectionString usando a classe EntityConnectionStringBuilder, a qual herda a partir de DbConnectionStringBuilder. Assim, você pode armazenar a localização dos seus arquivos metadata (.csdl. .msl, ssdl) em um arquivo de recurso e alterar via código o EntityConnectionString para apontar para esta localização. Você pode também querer alterar via código o provedor ADO .NET em tempo de execução.

No código exemplo a seguir lemos a string de conexão a partir do arquivo de configuração em uma string, em seguida criamos um EntityConnectionStringBuilder a partir daquela string,  modificamos a propriedade Metadata e então instanciamos um ObjectContext com a nova EntityConnectionString

Dim connstring = 
ConfigurationManager.ConnectionStrings.Item"MacorattiEntities").ConnectionString

Dim estringnew = New EntityConnectionStringBuilder(connstring)

With estringnew
     .Metadata = My.Settings.MetadataFilePath
     Dim context = New MacorattiEntities(estringnew.ToString)
     Dim query = From con In context.Contacts  Where _ 
                       con.Addresses.Any(Function(a) a.City = "Brasilia")
End With
var connstring = ConfigurationManager.ConnectionStrings["MacorattiEntities"].ConnectionString;

var estringnew = new EntityConnectionStringBuilder(connstring);
estringnew.Metadata = Properties.Settings.Default.MetadataFilePath;

var context = new MacorattiEntities(estringnew.ToString());

var query = from con in context.Contacts
                 where con.Addresses.Any((a) => a.City == "Brasilia")
                 select con;

Como o parâmetro Metadata é uma string, não existe uma maneira fortemente tipada de criá-la.

Abrindo e fechando conexões com Entidades e Banco de dados

O método Open da EntityConnection (EntityConnection.Open) carrega os arquivos de metadata (lidos do modelo) se eles não tiveram ainda sido carregados na memória da aplicação. O método Open da EntityConnection chama o método Connection.Open do provedor do banco de dados. Da mesma forma o método Close da EntityConnection irá chamar o método Close da Connection do banco de dados.

Quando um ObjectContext executa uma consulta internamente ela cria uma EntityConnection e um EntityCommand executa o comando; tão logo os dados foram usados, se você chamar um método como ToList para ler todos os dados de uma vez ou se você iterar através dos dados até o fim, o contexto irá fechar a EntityConnection a qual irá por sua vez fechar a conexão com o banco de dados.

E como fica o tratamento do pool de conexões ?

Esta é uma pergunta recorrente, mas como o pool de conexões é controlado pelo provedor do banco de dados, a Entity Framework não interage de forma explicita em como o pool de conexões trabalha.

 Desta forma apresentamos alguns conceitos básicos sobre o EntityConnection do EntityFramework.

Aguarde mais artigos da série Desvendando o EntityFramework.

Eu sei é apenas .NET, mas eu gosto...

Referências:


José Carlos Macoratti