Entity Framework - Conceitos Básicos - Exibindo Mestre-Detalhe


Neste artigo eu procuro dar uma visão geral sobre a utilização do Entity Framework para realização de tarefas básicas de manutenção de dados com alguns padrões usados em banco de dados. Para isso eu irei montar alguns cenários mostrando como usar o EF para realizar a tarefa de exibição e manutenção dos dados quando for o caso. Abaixo segue um resumo dos cenários que serão abordados:

Em todos os cenários irei usar uma aplicação Windows forms criada no Visual Studio 2008 SP1 e o banco de dados SQL Server 2008 Express.

Vou iniciar definindo o modelo básico usado na aplicação exemplo. Eu vou usar um banco de dados bem parecido com o Northwind.mdf mas com uma estrutura mais enxuta para facilitar o trabalho. Ele foi criado usando o SQL Server Management Studio 2008. Segue a baixo a estrutura do banco de dados que eu chamei Macoratti.mdf:

Nota: Veja o artigo : Usando o SQL Server Management Studio

 

Pegue o script para gerar o modelo acima aqui: MacorattiSQL.zip

Abra então o Visual Studio 2008 SP1 e crie um novo projeto do tipo Windows Forms chamado EF_Crud3;

A seguir vamos gerar um Entity Data Mode (EDM)l a partir do modelo exibido na figura acima;

No menu Project -> New Item , selecione em Templates o item ADO  .NET Entity Data Model e informe o nome Macoratti.edmx e clique em Add;

Dessa forma teremos o nosso modelo conceitual gerado conforme a figura a seguir:

Este será o nosso ponto de partida para as considerações e para os cenários que iremos desenhar para mostrar como usar o EF em algumas situações de manutenção de dados.

Cenário 3 - Exibindo Mestre - Detalhes

Neste cenário o que pretendemos e exibir as informações sobre categorias e produtos em um relacionamento do tipo Mestre-Detalhes onde em um DataGridView(gdvCategorias) serão exibidos as categorias e em outro DataGridView (gdvProdutos) serão os produtos relacionados, de forma que ao selecionar uma categoria os produtos relacionados seja automaticamente exibido.

Adicione um novo formulário frmMestreDetalhes.vb no projeto e inclua neste formulário os seguintes controles :  1 Button e 2 DataGridView conforme o leiaute abaixo:

Ao executar o projeto e selecionar uma categoria você quer exibir os seus produtos da seguinte forma:

Vejamos como obter este resultado usando o Entity Framework.

1- Exibindo as categorias no primeiro DataGridView

A primeira coisa que vamos fazer é definir uma consulta que deve obter os objetos Categoria e Produto a partir das entidades definidas no EDM.

Vamos declarar o seguinte namespace no projeto:

Imports System.Data.Objects

O namespace System.Data.Objects é usado para criar e gerenciar objetos de entidades e o EF usa o ObjectQuery para construir e executar consultas que retornam objetos.  Uma vez que um ObjectQuery tenha sido executado ele contém objetos tipados.

A Classe ObjectQuery(Of  T - Representa uma consulta contra o armazenamento no banco de dados e é formulada por meio de uma instrução de Entidade SQL , métodos de construtor de consultas ou Language-Integrated Query (LINQ).

A classe ObjectQuery representa uma consulta que retorna uma coleção objetos de entidades tipadas e sempre pertence a um contexto de objeto, no nosso caso ao contexto MacorattiEntities. Este contexto fornece a conexão e a informação necessária para compor e executar uma consulta e retorna uma instância tipada de ObjectQuery.

A classe ObjectQuery suporta tanto consultas LINQ to Entities como Entity SQL contra um Entity Data Model (EDM) e implementa um conjunto de métodos construtores que podem ser usados para construir comandos de consultas que são equivalentes aos métodos do Entity SQL.

Fazemos isso pois vamos usar consultas Entity SQL em nosso projeto.

A seguir devemos declarar a variável categoriaContexto como sendo do tipo ObjectContext:

Protected categoriaContexto As MacorattiEntities

Devemos incluir também um controle BindingSource no formulário com o nome bs que será usado para vinculação das categorias e produtos.

Agora no evento Load do formulário inclua o seguinte código:

   Private Sub frmMestreDetalhes_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'cria uma instância do ObjectContext
        categoriaContexto = New MacorattiEntities
        'defina consulta para obter as categorias e os produtos
        Dim categoria As ObjectQuery = categoriaContexto.Categorias.Include("Produtos")
        'atribui ao BindingSource o resultado da consulta
        bs.DataSource = categoria
        'atribui o BindingSource ao DatagridView para exibir as categorias
        gdvCategoria.DataSource = bs
        'Esconde a coluna Produtos (Navigation Properties)
        gdvCategoria.Columns("Produtos").Visible = False
        gdvCategoria.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
        'Efetua a vinculação dos produtos relacionados ao segundo DataGridView
        gdvProdutos.DataBindings.Add(New Binding("DataSource", bs, "Produtos"))
        'Esconde as colunas indicadas
        gdvProdutos.Columns("Categorias").Visible = False
        gdvProdutos.Columns("ItensPedidos").Visible = False
        gdvProdutos.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
    End Sub

Vamos explicar a consulta Entity SQL usada no código:

  Dim consulta As ObjectQuery(Of Categoria) = _
                                    categoriaContexto.Categorias.Include("Produtos")

A variável consulta é declarada como sendo do tipo ObjectQuery, que é uma classe no namespace System.Data.Objects. Dessa forma o Entity Framework irá criar e executar a consulta , usando o ObjectQuery, para retornar objetos, e esses objetos serão objetos que representam entidades no modelo conceitual (EDM) que foi gerado. Nesta consulta retornamos objetos da entidade Categoria.

Observe o comando Include("Produtos") na consulta que usa a habilidade do EF para usar as Navigation Properties como meio de criar vinculação entre dados relacionados.  Com isso estaremos carregando os objetos da entidade Produto.

Veja na figura ao lado mostra a entidade Categoria contendo uma Navigation Properties Produtos.

2- Exibindo os produtos relacionados no segundo DataGridView

Para exibir o resultado da seleção no segundo DataGridView usamos o código a seguir:

 'Efetua a vinculação dos produtos relacionados ao segundo DataGridView
 gdvProdutos.DataBindings.Add(New Binding("DataSource", bs, "Produtos"))

Os dados dos produtos são acessados através da Navigation Properties da entidade Categoria onde usamos a propriedade Produtos do objeto Categoria como uma fonte de dados através do BindingSource para o controle DataGridView.

Agora no evento Click do botão - Salvar alterações no banco de dados - vamos incluir o código para persistir as alterações na base de dados:

   Private Sub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click
        Try
            'salva as alterações feitas no banco de dados
            categoriaContexto.SaveChanges()
            MsgBox("Alteração salva com sucesso.")
        Catch ex As Exception
            MsgBox("Erro : " & ex.Message)
        End Try
    End Sub

 

Com isso podemos efetuar a manutenção tanto em Categorias como em Produtos e persistir as alterações feitas no banco de dados.

Simplesmente fantástico , não é mesmo !!!!

Mas não fique muito empolgado, o esquema apresentado aqui funciona porque o modelo usado é bem simples onde no relacionamento mestre-detalhe temos uma tabela representando a tabela mestre e uma tabela representando a tabela detalhe. Em relacionamentos mais complexos onde geralmente temos a utilização de  Views o esquema não vai funcionar.

Outro aspecto que deve ser destacado é que ao tentar excluir um registro da tabela Mestre e salvar o resultado poderá ocorrer um erro devido ao relacionamento entre as tabelas conforme a seguir:

"The DELETE statement conflicted with the REFERENCE constraint "FK_Produtos_Categorias". The conflict occurred in database "Macoratti", table "dbo.Produtos", column "categoriaid". The statement has been terminated."

Isto indica um conflito na tabela Produtos com a coluna Categoriaid.

Para poder  realizar a exclusão  você terá que alterar a regra de exclusão (Delete Rule) definida para a chave estrangeira FK_Produtos_Categorias  no banco de dados Macoratti.mdf definindo-a como Cascade.

Após realizar esta alteração a exclusão será permitida.

 

Como o meu objetivo nesta série de artigos é mostrar os recursos básicos do Entity Framework eu não estou preocupado com as boas práticas, estou apenas mostrando as possibilidades do framework que deverá estar mais robusto na sua segunda versão que será lançada em breve com o VS 2010.

Pegue o projeto completo aqui: EF_Crud3.zip

Eu sei é apenas Entity Framework , mas eu gosto.

Referências:


José Carlos Macoratti