Entity Framework 4.0 - Opções de Carga de dados (Lazy/Eager Loading)
A nova versão do Visual Studio, o Visual Studio 2010, lançado no final de abril trouxe dentre muitas novidades a tão esperada versão do Entity Framework, que passou a ser identificada como Entity Framework 4.0.
Segue abaixo um resumo das principais novidades desta versão do Entity Framework:
Essas novidades tornaram a utilização do EF4 mais fácil e aproximando-o mais do seu concorrente mais famoso o NHibernate.
Neste artigo vou mostrar algumas opções que temos para acessar e carregados.
Nosso ponto de partida será mostrar como gerar o modelo de entidades usando o Entity Data Model (EDM) e a seguir usar o modelo gerado para realizar as operações com a fonte de dados.
Criando o modelo de entidades - Entity Data Model (EDM)
O objetivo da ADO .NET Entity Framework é mais ambicioso; o serviço OR/M seria apenas mais um serviço e outros serviços como relatórios, sincronização, backup, etc. também seriam oferecidos; para cobrir todos estes serviços foi criado um modelo de dados que é similar ao usado no paradigma orientado a objetos que o desenvolvedor utiliza, e também é independente de qualquer linguagem ou plataforma.
Este modelo de dados é conhecido como Entity Data Model (EDM) ou modelo de entidades de dados e pode ser considerado o coração da do Entity Framework.
O
EDM é um modelo
entidades-relacionamentos onde :
|
É a partir do modelo de entidades que podemos escrever código usando as diferentes APIs , como o provedor EntityClient ou o Object Services com LINQ to Entities.
O Visual Studio oferece um assistente para a criação do EDM a partir do seu banco de dados ou do seu modelo de entidades.
Para criar um EDM a partir de um banco de dados relacional podemos usar o Visual Studio 2010, o VB 2010 Express Edition ou o Visual C# 2010 Express Edition.
Após criar um projeto Windows Forms, Web Application, WPF Application, etc. e a seguir clique com o botão direito sobre o nome do projeto e selecione Add -> New Item e na janela Add New Item selecione Data -> ADO .NET Entity Data Model e informe o nome Northwind.edmx pois vamos gerar o modelo de entidades a partir do banco de dados Northwind.mdf;
O assistente irá apresentar a tela do Entity Data Model Wizard onde temos as opções de gerar o modelo a partir do banco de dados ou de um modelo vazio;
Vamos gerar o modelo a partir do banco de dados Northwind.mdf portanto selecione o item Generate from database e clique em Next>;
O assistente irá apresenta a janela para você escolher a conexão. Definindo a conexão para o Northwind.mdf vemos a string de conexão da entidade e nome com a qual ela será salva no arquivo App.Config;
Na próxima janela vamos escolher quais tabelas do banco de dados irão fazer parte do modelo de entidades e para as quais será gerado o mapeamento objeto relacional;
Eu vou selecionar apenas as tabelas Categories e Products para fica mais fácil visualizar o modelo;
Ao final será gerado o arquivo Northwind.edmx que representa o modelo de entidades. No descritor podemos ver as entidades, o mapeamento gerado pelo EF4;
Com isso estamos prontos para usar o modelo de entidades gerado.
Agora que o temos o EDM gerado podemos acessar os dados de forma bem simples pois o EF gerou as entidades e todo o mapeamento com as tabelas do banco de dados criando um contexto a partir do qual temos os métodos para acessar, editar e excluir as informações das entidades persistindo-as no banco de dados.
Com isso você não vai precisar mais usar os objetos ADO .NET para abrir e fechar conexões nem acessar os dados nem com comandos SQL para realizar as tarefas básicas de manutenção de dados.
A partir deste momento você tem acesso ao modelo de entidades e pode realizar consultas usando o LINQ to Entities obtendo listas de objetos e objetos e usando uma sintaxe bem mais próxima da linguagem de alto nível que estamos usando.
EF - Carregando dados com Lazy/Eager Loading
Se estamos trabalhando com uma fonte de dados relacional usando Entity Framework 4 mais cedo ou mais tarde teremos que carregar os dados para exibição e/ou manutenção.
Veremos algumas opções que temos usando o EF4 para carregar dados baseado no EDM que geramos no início do artigo.
Apenas para recordar vou repassar conceitos de Lazy Loading e Eager Loading que serão usados no artigo:
Lazy Loading - é o mecanismo utilizado pelos frameworks de persistência para carregar informações sob demanda. Esse mecanismo torna as entidades mais leves, pois suas associações são carregadas apenas no momento em que o método que disponibiliza o dado associativo é chamado. Assim quando objetos são retornados por uma consulta, os objetos relacionados não são carregados ao mesmo tempo, ao invés, eles são carregados automaticamente quando a propriedade de navegação for acessada.
Eager Loading - é o mecanismo pelo qual uma associação, coleção ou atributo é carregado imediatamente quando o objeto principal é carregado. Dessa forma todas as relações de uma entidade serão carregadas no mesmo momento em que esta entidade é carregada. É o contrário do Lazy Loading.
1- Carregando dados usando Lazy Loading ativado (padrão)
Eu vou usar o Visual Basic 2010 Express Edition e criar uma aplicação Windows Forms Application com o nome EF4_CarregaDados;
No formulário form1.vb do projeto vamos incluir um controle Button(id=btnCarregar) e um controle ListBox(id=lstDados) conforme o leiaute abaixo:
Nosso objetivo será exibir os produtos por categorias no controle ListBox(lstDados).
Para isso vamos incluir o código a seguir no evento Click do botão Carregar Dados:
Private Sub btnCarregar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCarregar.Click 'lazy loading esta ativo Using ctx = New NORTHWNDEntities Dim categorias = From c In ctx.Categories Select c For Each cat In categorias lstDados.Items.Add("Categoria : " & cat.CategoryName & vbCrLf) lstDados.Items.Add("Produtos: Código / Nome ") For Each prod In cat.Products lstDados.Items.Add(prod.ProductID & " - " & prod.ProductName) Next Next End Using End Sub |
Usando o contexto criado pelo EDM estamos obtendo as categorias existentes: Dim categorias = From c In ctx.Categories Select c
A seguir usando um laço for/each percorremos as categorias e listamos o seu nome : lstDados.Items.Add("Categoria : " & cat.CategoryName & vbCrLf)
Em outro laço for/each verificamos cada produto existente na categoria atual e o exibimos o ListBox: lstDados.Items.Add(prod.ProductID & " - " & prod.ProductName)
Executando o projeto iremos obter:
Neste cenário estamos usando o lazy loading (que esta ativo por padrão).
- Podemos usar esta opção quando
tivermos uma situação de navegação por paginação de dados e
somente quando o usuário requisitar pois envolve múltiplas
chamadas;
- Quando for preciso passar informações entre camadas não
devemos usar esta opção pois não teremos um contexto ativo
aberto.
2- Carregando dados usando Lazy Loading desabilitado
Neste cenário vamos controlar o Lazy Loading carregando os dados somente quando requerido.
Para fazer isso vamos desativar o Lazy Loading e fazer a chamada a ele de forma explicita.
Vamos incluir outro controle Button (id=btnCarregar2) - Carregar Dados -Lazy Loading Inativo - e no seu evento Click incluir o seguinte código:
Private Sub btnCarregar2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCarregar2.Click Using ctx = New NORTHWNDEntities 'desativando o lazy loading ctx.ContextOptions.LazyLoadingEnabled = False Dim categorias = From c In ctx.Categories Select c For Each cat In categorias lstDados.Items.Add("Categoria : " & cat.CategoryName & vbCrLf) lstDados.Items.Add("Produtos: Código / Nome ") 'carregando os produtos da categoria If 1 = 1 Then cat.Products.Load() End If For Each prod In cat.Products lstDados.Items.Add(prod.ProductID & " - " & prod.ProductName) Next Next End Using End Sub |
Observe que estamos desativando o Lazy Loading => ctx.ContextOptions.LazyLoadingEnabled
= False
E que estamos fazendo a carga dos produtos explicitamente :
If 1 = 1
Then
cat.Products.Load()
End If
Se não fizermos isso , somente as categorias serão carregadas e
o resultado será o seguinte:
Neste cenário estamos controlando o número de chamadas com base na necessidade da aplicação usando um condição.
3- Carregando dados com Eager Loading
Se desabilitarmos o Lazy Loading conforme o cenário acima e precisarmos obter todos os dados disponíveis na memória teremos que usar método Include(entidade) para obter os dados;
Vamos incluir outro controle Button (id=btnCarregar3) - Carregar Dados - Eager Loading- e no seu evento Click incluir o seguinte código:
Private Sub btnCarregar3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCarregar3.Click Using ctx = New NORTHWNDEntities 'desativando o lazy loading ctx.ContextOptions.LazyLoadingEnabled = False 'usando o método Include para carregar os produtos relacionados Dim categorias = From c In ctx.Categories.Include("Products") Select c For Each cat In categorias lstDados.Items.Add("Categoria : " & cat.CategoryName & vbCrLf) lstDados.Items.Add("Produtos: Código / Nome ") For Each prod In cat.Products lstDados.Items.Add(prod.ProductID & " - " & prod.ProductName) Next Next End Using End Sub |
Observe que estamos desativando o Lazy Loading => ctx.ContextOptions.LazyLoadingEnabled
= False
E que estamos fazendo a carga dos produtos relacionados com a
categoria usando o método Include:
Dim categorias = From c In ctx.Categories.Include("Products") Select c
Executando o projeto iremos obter o seguinte resultado:
Neste cenário estamos obtendo todas as categorias e os produtos em uma única consulta.
Isto é necessário quando estamos passando informações entre camadas.
Esta opção reduz o número de chamadas mas pode carregar uma grande quantidade de dados e pode ser crítico se houver pouca memória.
Também podemos combinar as opções que foram vistas no artigo, e assim usar Lazy Loading e o método Include dependendo do cenário.
Simples, simples assim...
Pegue os projetos completos aqui: EF4_CarregaDados.zip
Eu sei é apenas Entity Framework 4, mas eu gosto...
Referências: