Entity Framework - conceitos básicos : Incluindo, modificando e excluindo objetos I


Este série de artigos é dedicada ao Entity Framework e tem o objetivo de dar uma introdução básica e uma visão geral de como usar este importante recurso da plataforma .NET. Os artigos são parcialmente baseados na documentação da MSDN de onde são citadas as respectivas referências.

Iniciando com o Entity Framework

Conceito

A ADO .NET Entity Framework foi projetado para permitir que a criação de aplicações com acesso a dados use o modelo de programação feito contra um modelo conceitual ao invés do antigo modelo de programação feito diretamente contra um banco de dados relacional. O objetivo é diminuir a quantidade de código e o tempo de manutenção necessária exigida nestas aplicações orientada a dados.

A ADO .NET Entity Framework é uma framework que abstrai o esquema de um banco de dados relacional e o apresenta como um modelo conceitual. Abaixo a figura que representa a arquitetura em camadas do Entity Framework: (Até o lançamento do VS 2010, previsto para o primeiro trimestre.)

Data Source :  Representa a base da arquitetura onde estão armazenados os dados;

Data Providers :  Os dados são acessados por um ADO.NET data provider.  Até o momento tanto o SQL Server como o MySQL são suportados e provavelmente em breve os principais RDBMS do mercado (Oracle, MySQL, DB2, Firebird, Sybase, VistaDB, SQLite, ...) terão um provider para o EF.

Entity Data Model (EDM) :  O  Entity Data Model  é constituído de 3 partes:

  • Conceptual schema definition language (CSDL) : Declara e define entidades, associações, herança, etc,. As Entity classes são geradas a partir deste esquema;
  • Store schema definition language (SSDL) : Metadados que descreve o container de armazenamento (=banco de dados) que persiste os dados;
  • Mapping specification language (MSL) : Mapeia as entidades no arquivo CSDL para tabelas descritas no arquivo SSDL;

Entity Client : O EntityClient é um provedor gerenciado ADO.NET que suporta o acesso a dados descritos no EDM. Ele é similar ao SQLClient, e fornece diversos componentes como EntityCommand, EntityConnection e EntityTransaction;

Object Services : Este componente permite realizar consultas, atualizações, inclusões e exclusões nos dados, expressados como objetos CLR fortemente tipados que são instâncias de entity types. Ele da suporte tanto a consultas Entity SQL como LINQ to Entities;

Entity SQL (ESQL) : É uma derivação da Transact-SQL, projetada para consultar e manipular entidades definidas no EDM. Ele dá suporte herança e associação sendo que tanto os componentes Object Services como os componentes Entity Client podem executar instruções Entity SQL;

LINQ to Entities : É uma linguagem de consulta fortemente tipada para consultar entidades definidas no EDM;
 

Quando você esta aprendendo uma nova forma de tratar os dados através do mapeamento objeto relacional um ponto importante a considerar e saber como incluir, modificar e alterar as informações do modelo conceitual  de modo que elas se reflitam no modelo de dados relacional.

Vejamos então como incluir, modificar e alterar objetos no Entity Framework. Para isso vamos gerar um modelo conceitual a partir do banco de dados Northwind.mdf usando o assistente do EntityFramework criando um Entity Data Model (EDM) e um ObjectContext a partir do qual iremos basear as nossas ações.

Para acompanhar o exemplo você vai precisar dos seguintes recursos:

1-) Abra o VS 2008 e crie um novo projeto do tipo Windows Forms Application usando a linguagem Visual Basic com o nome de EF_crud1;

2-) A seguir no menu Project selecione Add New Item;

3-) Na janela Add New Item, em Templates selecione ADO .NET Entity Data Model, informe o nome Northwind.edmx e clique em Add;

4-) Seguindo o assistente selecione o item : Generate From DataBase  e clique em Next> ;

5-) Na próxima janela do assistente aceite o nome NorthwindEntities e clique em Next> ;

6-) Na próxima janela selecione todas as tabelas, aceite o nome para Model Namespace como NorthwindModel, e clique no botão Finish;

Abaixo temos o modelo conceitual representado graficamente no descritor do EF. Além disso foi gerado o ObjectContext que gerencia o estado dos objetos e permite realizar operações CRUD.

Eu fiz questão de mostrar como gerar o EDM pois ele será a nossa base de operações. Agora vamos ao que interessa...

Os objetos gerados e representados no EDM , um contexto de objetos, são instâncias de entidades de tipos que representam os dados em uma fonte de dados. Lembre-se sempre que estamos tratando com objetos e não com tabelas.

Você pode modificar , criar e excluir objetos no contexto do domínio e para fazer isso você usa o componente Object Services. É ele que gerencia as alterações feitas nos objetos e permite realizar estas operações.

Para efetivamente realizar a operação desejada você usa o método SaveChanges(),  dessa forma o Object Services gera e executa comandos que realizam as operações equivalentes de inclusão, atualização ou exclusão contra a fonte de dados.

Agora vamos mostrar como realizar as operações CRUD (create, update, delete) no contexto gerado pelo EF.

Vamos escolher as entidades Orders e Orders_Details conforme o detalhe da figura abaixo retirado do modelo gerado para o nosso exemplo:

Na minha versão do VS 2008 o EDM gera as entidades com os mesmos nomes que elas estão definidas no banco de dados, ou seja, no plural (Orders).

Para melhor refletir a realidade vamos alterar o nome das entidades deixando-os no singular.

Assim teremos as seguintes mudanças:

1- Orders  para Order

2- Order_Details para Order_Detail

Na figura abaixo vemos as alterações feitas.

 

Além disso uma entidade no descritor esta separada em duas partes :  A primeira consiste de valores escalares e a segunda contém as Navigation Properties que permitem a uma entidade acessar uma entidade de referência ou uma coleção de entidades.

O nosso foco será o relacionamento entre a entidade Order e Order_Detail representada pela propriedade de navegação: Order_Details na entidade Order e pela propriedade de navegação Orders na entidade Order_Detail.

O relacionamento indica que um pedido (order) pode ter muitos detalhes de pedidos (order_details) e um detalhe de pedido precisa pertencer a um pedido.

Vamos carregar os pedidos em uma combobox exibindo o código do pedido e  depois realizar uma consulta que retorna um objeto Order e uma coleção de objetos Order_Detail relacionados. O pedido será exibido em um controle ListBox e os detalhes do pedido em um DataGridView.

A seguir vamos repetir a consulta e percorrendo a coleção vamos realizar a seguintes operações:

Então vamos incluir no formulário form1.vb os controles : Combobox, ListBox, Button e DataGridView conforme o leiaute abaixo:

Agora vamos ao código...

Para começar faça a declaração abaixo que define uma variável (dc) do tipo NorthwindEntities assim teremos acesso a uma instância do nosso contexto de domínio.

Dim dc As NorthwindEntities

A seguir no evento Load do formulário vamos incluir o código para obter os objetos Order e exibi-los no controle Combobox:

 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        dc = New NorthwindEntities
        Dim consulta = From o In dc.Orders Select o
        cboPedidos.DisplayMember = "OrderID"
        cboPedidos.ValueMember = "OrderID"
        cboPedidos.DataSource = consulta.ToList

    End Sub

O código cria uma nova instância para o ObjectContext e efetua uma consulta retornando todos os objetos da entidade Order;

Em seguida configuramos o controle Combobox para exibir o código do pedido(OrderID) retornados e tratar o valor selecionado pelo código do pedido (OrderID);

O código associado ao evento Click do botão Exibir Pedidos e detalhes do Pedido esta descrito a seguir:

Private Sub btnExibirAlteracoes_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExibirAlteracoes.Click
        Dim id As Integer = cboPedidos.SelectedValue
        Dim pedido = (From p In dc.Orders _
                            Where p.OrderID = id _
                            Select p).First
        lstPedido.Items.Clear()
        lstPedido.Items.Add("OrderID   : " & pedido.OrderID)
        lstPedido.Items.Add("OrderDate : " & pedido.OrderDate)
        lstPedido.Items.Add(pedido.RequiredDate)
        lstPedido.Items.Add(pedido.ShipAddress)
        lstPedido.Items.Add(pedido.ShipCity)
        lstPedido.Items.Add(pedido.ShipCountry)
        lstPedido.Items.Add(pedido.ShipName)
        lstPedido.Items.Add(pedido.ShipPostalCode)
        pedido.Order_Details.Load()
        lblItens.Text = pedido.Order_Details.Count

        gdvDetalhesPedido.DataSource = pedido.Order_Details
    End Sub

Neste código obtemos o código do pedido (OrderID) selecionado a partir da combobox na variável id e efetuamos uma consulta para obter o pedido com respectivo código:

 Dim id As Integer = cboPedidos.SelectedValue
 Dim pedido = (From p In dc.Orders _
                       Where p.OrderID = id _
                       Select p).First

A seguir exibimos no controle ListBox os dados do pedido:

        lstPedido.Items.Clear()
        lstPedido.Items.Add("OrderID   : " & pedido.OrderID)
        lstPedido.Items.Add("OrderDate : " & pedido.OrderDate)
        lstPedido.Items.Add(pedido.RequiredDate)
        lstPedido.Items.Add(pedido.ShipAddress)
        lstPedido.Items.Add(pedido.ShipCity)
        lstPedido.Items.Add(pedido.ShipCountry)
        lstPedido.Items.Add(pedido.ShipName)
        lstPedido.Items.Add(pedido.ShipPostalCode)

Depois carregamos os detalhes dos pedidos do referido pedido usando o método Load;

 pedido.Order_Details.Load()

Exibimos a quantidade de itens contidos no detalhes do pedido usando a propriedade Count:

lblItens.Text = pedido.Order_Details.Count

E finalmente exibimos os detalhes do pedido no controle DataGridView:

    gdvDetalhesPedido.DataSource = pedido.Order_Details

Vejamos agora o código do evento Click do botão Realizar alterações nos objetos onde vamos realizar as alterações nos objetos do contexto e depois usar o método SaveChanges para persistir as alterações no banco de dados:

    Private Sub btnExibirPedido_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExibirPedido.Click
        Dim id As Integer = cboPedidos.SelectedValue
        Dim pedido = (From p In dc.Orders _
                            Where p.OrderID = id _
                            Select p).First
        ' altera a cidade e data requerida do pedido
        pedido.ShipCity = ">>Brasilia"
        pedido.RequiredDate = DateAndTime.Today
        'Carrega os items para o pedido se não estiver carregado
        If Not pedido.Order_Details.IsLoaded Then
            pedido.Order_Details.Load()
        End If
        'Exclui o primeiro item do pedido
        dc.DeleteObject(pedido.Order_Details.First())
        ' Salva as alterações no object context para o banco de dados
        Dim controle = dc.SaveChanges()
        MsgBox("Alterações realizadas com sucesso")
    End Sub

 

Aqui obtemos o objeto pedido (Order) selecionado e alteramos a cidade de envio (ShipCity) e a data da requisição (RequireData);

   ' altera a cidade e data requerida do pedido
    pedido.ShipCity = ">>Brasilia"
    pedido.RequiredDate = DateAndTime.Today

A seguir carregamos os detalhes para este pedido e excluímos o primeiro item do pedido:

   'Exclui o primeiro item do pedido
   dc.DeleteObject(pedido.Order_Details.First())

Para encerrar persistimos as alterações através do método SaveChanges:

    Dim controle = dc.SaveChanges()

Observe que o retorno obtido é o número de objetos no estado Added, Modified e Deleted quando o método foi chamado.

Abaixo temos o resultado para um pedido selecionado:

Para ter certeza de que os objetos no cliente foram atualizados você pode chamar o método Refresh com o valor StoreWins depois de chamar SaveChanges.

Pegue o projeto completo aqui: EF_crud1.zip

Eu sei é apenas Entity Framework  mas eu gosto...

Referências:


José Carlos Macoratti