WPF - DataGrid : CRUD com Entity Framework 4.1 (C#)


Neste tutorial eu vou mostrar como realizar as operações CRUD em uma aplicação WPF usando o DataGrid e o Entity Framework 4.1 com a linguagem C#.

Abra o Visual C# 2010 Express Edition, opção File-> New Project, e crie uma nova aplicação WPF com o nome: CURDDataGridWPF;

Definindo a fonte de dados

Como fonte de dados eu vou usar um banco de dados SQL Server criado no SQL Server Management Studio (veja referências) com o nome Cadastro.mdf e a tabela Autores que possui os campos: autorid,nome, email e telefone.

Abaixo podemos ver na figura, o banco de dados , a tabela e seus campos:

Para acessar e realizar as operações CRUD eu poderia usar os assistentes, um DataSet, o NHibernate, o LInq To SQL mas neste artigo eu vou usar o Entity Framework 4.1 para mostrar com é simples trabalhar com o acesso a dados com essa ferramenta.

Quando pensamos em acesso a dados na plataforma .NET pensamos em ADO .NET , certo ?

Pois bem, como fazemos atualmente para acessar os dados em um banco relacional com ADO .NET ?

Geralmente efetuamos a representação das tabelas do banco de dados em classes de forma a criar uma interface para persistência das informações.

Isso é feito hoje basicamente de duas formas:

  1. Fazer o mapeamento objeto-relacional usando DataSets e o acesso a dados através de DataAdapters ou TableAdapters com ajuda dos Assistentes de configuração;
  2. Fazer o mapeamento objeto-relacional através da criação das classes de negócio via código e acessando os dados usando DataReader;

Neste projeto vou usar a ferramenta OR/M da Microsoft chamada Entity Framework que esta na sua versão 4.1.

O objetivo da ADO .NET Entity Framework é ser mais que um OR/M; 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 :
  • Entidades - são instâncias de tipos de entidades como Clientes, Produtos os quais estão estruturados em registros e chaves;
  • Relacionamentos - são instâncias de tipos de relacionamentos que são associações entre duas ou mais tipos de entidades;

É 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.

Agora vamos incluir a partir do menu Project->Add New Item , a partir da janela Templates, o item Entity Data Model alterando o nome para Autores.edmx e clicando no botão Add;

Na próxima janela selecione a opção Generate from database, pois vamos gerar o modelo de entidades a partir de um banco de dados existente, e clique em Next>;

Na janela Entity Data Model do assistente verifique se a conexão com o banco Cadastro.mdf esta selecionada (se não existir você deverá criar clicando no botão New Connection);

Aceite os nomes que foram sugeridos pelo assistente, dessa forma o nome CadastroEntities será o nome do seu container do modelo de entidades e o arquivo de configuração App.Config terá a entity connection que será usada para realizar a conexão com o banco de dados;

Neste momento será exibida a janela do descritor Objeto Relacional. Expanda os objetos do banco de dados Cadastro.mdf e selecione a tabela Autores e click em Finish;

A tabela do banco de dados será mapeada como uma classe (campos como propriedades, procedures e funções como métodos)  e você terá no Descritor a classe Autor que representa a tabela Autores do banco de dados;

O arquivo Autores.edmx contém o arquivo XML com informações sobre o leiaute da tabela que foi mapeada e também o descritor contendo a classe gerada pelo mapeamento. Após encerrar o mapeamento você já terá acesso aos recursos do Entity Framework com direito a intellisense completo das informações referente a tabela mesmo sem conhecer nada sobre ela. Se você abrir a janela de propriedades verá que o arquivo Autores.edmx será identificado pelo nome CadastroEntities representando o nosso contexto de entidades.

Definindo a interface

Vamos agora criar no arquivo MainWindow.xaml a interface da nossa aplicação que irá exibir os dados da tabela Autores. Para isso vou usar um controle DataGrid(name=dgData) e um controle TextBlock (name=txtStatus), usado para exibir mensagens, definidos conforme o leiaute da figura abaixo onde podemos ver também o código XAML gerado:

Note que devemos tratar os eventos : RowEditEnding e PreviewExecuted do Command e que definimos o DataGrid para permitir ao usuário incluir e excluir linhas: CanUserAddRows e CanUserDeleteRows

Agora abra o arquivo MainWindow.xaml.vb e defina os namespaces que iremos usar:

using System.Linq;
using System.Windows;
using System.Windows.Input;
using Microsoft.Windows.Controls;

A seguir inclua o seguinte código no evento Loaded da janela Window:

void Window1_Loaded(object sender, RoutedEventArgs e)
{
    CadastroEntities context = new CadastroEntities();
    var result = from aut in context.Autores
    select aut;
     if (result.ToList().Count > 0)
     {
           txtStatus.Text = "Leitura feita com sucesso";
     }

     dgData.ItemsSource = result.ToList();
}

Se você executar o código agora (não esqueça de definir os eventos : dgData_PreviewExecuted e dgData_RowEditEnding) deverá obter o seguinte resultado:

Agora no evento dgData_RowEditEnding vamos incluir o código para realizar a inclusão e atualização dos dados conforme abaixo:

      private void dgData_RowEditEnding(object sender, DataGridRowEditEndingEventArgs e)
        {
            if (e.EditAction == DataGridEditAction.Commit)
            {
                CadastroEntities context = new CadastroEntities();
                Autor autor = e.Row.DataContext as Autor;

                var _resultado = (from a in context.Autores where a.autorid == autor.autorid select a).SingleOrDefault();

                if (_resultado == null)
                {
                    Autor _autor = new Autor();
                    _autor.nome = autor.nome;
                    _autor.email = autor.email;
                    _autor.telefone = autor.telefone;

                    context.AddToAutores(_autor);
                    context.SaveChanges();

                    txtStatus.Text = "Dados incluídos com sucesso.";
                }
                else
                {
                    _resultado.nome = autor.nome;
                    _resultado.email = autor.email;
                    _resultado.telefone = autor.telefone;

                    context.SaveChanges();
                    txtStatus.Text = "Dados atualizados com sucesso.";
                }
            }
        } 

Na linha de código  context.AddToAutores(_autor) o método AddTo<EntityName>,  que é gerado pelo EF baseado nas entidades geradas a partir do banco de dados, irá realizar a inclusão do novo objeto no contexto.

Para concluir usamos o método SaveChanges() do contexto para persistir as alterações no banco de dados.

Para excluir um registro vamos usar o evento dgData_PreviewExecuted incluído nele o código abaixo:

      private void dgData_PreviewExecuted(object sender, ExecutedRoutedEventArgs e)
        {
            CadastroEntities context = new CadastroEntities();
            Autor _autor = dgData.SelectedItem as Autor;
            
            if (_autor != null)
            {
                var _resultado = (from aut in context.Autores where aut.autorid == _autor.autorid select aut).SingleOrDefault();

                if (e.Command == DataGrid.DeleteCommand)
                {
                    if (!(MessageBox.Show("Deseja excluir este registro ?", 
                        "Confirma a Exclusão !", MessageBoxButton.YesNo) == MessageBoxResult.Yes))
                    {
                        e.Handled = true;
                    }
                    else
                    {
                        context.Autores.DeleteObject(_resultado);
                        context.SaveChanges();
                        txtStatus.Text = "Registro excluido com sucesso.";
                    }
                }
            }
        }

O evento PreviewExecuted ocorre quando o método Execute de um RoutedCommand é chamado. O CommandManager é o responsável por gerenciar os comandos roteados.

Para excluir um registro realizamos uma consulta para obter a entidade selecionada e a seguir usamos o método DeleteObject() para marcar o objeto para deleção a partir do ObjectStateManager, sendo que o objeto é efetivamente excluído quando o método SaveChanges é chamado.

Executando o projeto e realizando as operações previstas iremos obter:

Atualizando dados (digitando diretamente no GRID)
Incluindo um novo Aluno (digitando diretamente no GRID)
Excluindo um aluno (Pressionando a tecla DEL)

Assim pudemos conferir a utilização do Entity Framework em uma aplicação WPF para realizar as operações CRUD em um banco de dados SQL Server.

Pegue o projeto completo aqui:   CRUDDataGridWPF.zip

"Jesus dizia pois aos judeus que criam nele: Se vós permanecerdes na minha palavra, verdadeiramente sereis meus discípulos. E conhecereis a verdade e a verdade os libertará." (João 8:31-32)

Referências:


José Carlos Macoratti