SilverLight 4 - Usando o Entity Framework 4 com um serviço WCF (C#)


Este artigo mostra como obter dados a partir de um  Entity Data Model do Entity Framework 4 em uma aplicação SilverLight 4.

O Entity Framework 4 é o framework ORM da Microsoft que transforma objetos de negócio em dados relacionais e vice-versa. O foco do Entity Framework não é o banco de dados mas o modelo de negócios e dessa forma uma de suas tarefas e gerar o modelo conceitual a partir do modelo de banco de dados, feito este serviço o desenvolvedor não tem que lidar mais diretamente com o banco de dados mas com o modelo conceitual e o modelo de entidades.

Neste artigo vamos usar os recursos do Entity Framework para gerar um Entity Data Model(EDM) para a tabela Categorias do banco de dados Macoratti.mdf (este banco de dados foi criado no SQL Server 2005 com base no Northwind.mdf só que mais simples). O EDM descreve o banco de dados, o modelo de classes e o mapeamento das mesmas e é esse mapeamento que simplifica a tarefa do desenvolvedor.

A seguir você vê a estrutura da tabela Categorias do banco de dados Macoratti.mdf usada neste artigo:

Obs: Os scripts para gerar o Banco de dados Macoratti.mdf e a tabela Categorias no SQL Server Management Studio Express estão contidos no pacote do projeto.

No exemplo deste artigo vamos incluir um EDM em nossa solução SilverLight 4 e escrever os métodos necessários para obter e atualizar os dados da tabela Categorias e conectar a nossa aplicação SilverLight a um serviço WCF chamando estes métodos.

Quais os recursos necessários que devemos ter instalados:

1 - Precisamos ter instalado o Visual Studio 2010 ou o Visual Web Developer Express 2010 ;
2 - Precisamos ter instalado o
SilverLight 4 Tools for Visual Studio 2010;

Obs: Para o exemplo mostrado neste artigo eu estou usando o Visual Web Developer 2010 Express Edition.

Vamos usar o Visual Web Developer 2010 Express Edition mas você pode usar também o Visual Studio 2010.

Objetivo : Criar uma aplicação SilverLight 4 para obter e atualizar dados da tabela Categorias usando o Entity Framework e um serviço WCF

premissas:

- Definir um Entity Data Model para a tabela Categorias;
- Definir a classe que representa uma Categoria e fará o papel do Data Transfer Object;
- Definir os métodos para obter e atualizar dados;
- Criar um serviço WCF que irá usar os métodos definidos no item anterior;
- Definir uma aplicação SilverLight que será usada como interface com o usuário;

Abra o Visual Web Developer 2010 Express Edition e crie um novo projeto com o nome SilverLight4_EF4 usando a linguagem C#;

No menu File-> New Project selecione Visual Basic -> SilverLight e a seguir o template SilverLight Application informando o nome SilverLight4_EF4;

Clique em OK;

Na seguinte janela de diálogo apenas confirme as opções e clique em OK;

Será criado uma solução com dois projetos: O projeto SilverLight e o Projeto Web;

Nossa próxima tarefa será criar o Entity Data Model partindo do modelo de dados que será o banco de dados Macoratti.mdf e a tabela Categorias;

Obs: Para simplificar e por não ser o foco deste artigo eu não vou listar o passo a passo de como criar o EDM, nas referências existem links com exemplos que mostram a geração do EDM em detalhes;

Etapas para gerar o EDM:

  1. Selecione o projeto SilverLight4_EF4.Web e no menu Project -> Add New Item, selecione Data e a seguir ADO .NET Entity Data Model, informe o nome Macoratti.edmx e clique no botão Add;
  2. A seguir selecione : Generate From DataBase e clique em Next>;
  3. Escolha a conexão com o banco de dados Macoratti.mdf ou o banco de dados de sua escolha e clique em Next>;
  4. Selecione a tabela Categorias e clique em Finish;

O modelo de entidades gerado esta representado no arquivo Macoratti.edmx e pode ser visto na figura a seguir:

Agora vamos criar a classe CategoriaDTO.cs que irá representa a tabela Categoria;

Selecione o projeto SilverLight4_EF4.Web e no menu Project -> Add Class e a na próxima janela informe o nome CategoriaDTO.cs;

A seguir inclua o seguinte código nesta classe:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
namespace Silverlight4_EF4.Web
{
    [DataContract]
    public class CategoriaDTO
    {
        [DataMember]
        public int CategoriaID { get; set; }

        [DataMember]
        public string CategoriaNome { get; set; }

        [DataMember]
        public string CategoriaDescricao { get; set; }

        public CategoriaDTO(int id, string nome,  string desc)
        {
            this.CategoriaID = id;
            this.CategoriaNome = nome;
            this.CategoriaDescricao = desc;
        }
    }
}

Esta classe vai ser usada pelo Serviço WCF que iremos criar mais adiante e por isso ela foi definida com um Contrato de Dados.

Contratos de Dados (Data Contracts) - Descreve a estrutura de dados usada no serviço. (Mapeia tipos CLR para XSD).  Um Data Contract é um acordo formal entre um serviço e um cliente que descreve os dados que serão trocados entre ambos. Para estabelecer a comunicação, o cliente e o serviço não necessitam trocar necessariamente os mesmos tipos de dados, devem trocar apenas os mesmos data contracts.

Um Data Contract especifica para cada parâmetro ou tipo de retorno qual informação será serializada (convertida em XML) para ser trocada.  Os DataContracts são definidos através de classes e uma classe DataContract deverá ser decorada com o atributo DataContract e os campos e propriedades que o tipo possui devem ser decorados com o atributo DataMember. (A partir do service pack  versão 3.5 da plataforma .NET isso não é mais obrigatório)

A seguir vamos criar um serviço WCF no projeto Web SilverLight4.EF4.Web.

No menu Project selecione Add New Item e a seguir selecione SilverLight-> SIlverLight-enabled WCF Service e informe o nome CategoriaService.svc e clique em  Add;

Agora vamos definir no serviço CategoriaService.svc dois métodos:

Abaixo temos o código do serviço:

using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;

namespace Silverlight4_EF4.Web
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class CategoriaService
    {
        [OperationContract]
        public List<CategoriaDTO> GetCategorias()
        {
            using (var ctx = new MacorattiEntities())
            {
                List<CategoriaDTO> categoria = new List<CategoriaDTO>();
                foreach (var item in ctx.Categorias.Where(c => c.categorianome.StartsWith("V")))
                {
                    categoria.Add(new CategoriaDTO(item.categoriaid, item.categorianome, item.categoriadescricao));
                }
                return categoria;
            }
        }

        [OperationContract]
        public bool SaveCategoria(CategoriaDTO categoriaSalvar)
        {
            try
            {
                using (var ctx = new MacorattiEntities())
                {
                    Categoria categoriaAtual = ctx.Categorias.First<Categoria>(c => c.categoriaid == categoriaSalvar.CategoriaID);
                    categoriaAtual.categorianome = categoriaSalvar.CategoriaNome;
                    ctx.SaveChanges();
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}

Acima temos um contrato de Serviço que descreve operações que um serviço pode realizar.

Para implementar um serviço WCF iniciamos pela definição do contrato para o serviço e então implementamos o contrato em um tipo de serviço. Um contrato para um serviço geralmente envolve a aplicação do atributo ServiceContract para uma interface e então a aplicação do atributo OperationContract para cada método exposto como parte do contrato do serviço.

Agora que já temos o serviço WCF definido vamos incluir uma referência ao serviço no projeto SilverLight SilverLight4_EF4.

Selecione o projeto SilverLight4_EF4 e no menu Project selecione Add Service Reference;

Na janela de diálogo abaixo clique no botão Discover para selecionar o seu serviço pois ele esta na mesma solução.

Você deverá ver os métodos GetCategorias e SaveCategoria definidos no serviço WCF, exibidos na caixa Operations;

A seguir informe CategoriaService no campo Namespace;

Clicando no botão OK o serviço estará disponível a partir da aplicação SilverLight;

Então vamos ajeitar a nossa interface que é a aplicação SilverLight.

Abra a página MainPage.xaml defina o leiaute conforme a figura abaixo:

O Código XAML para a interface acima é o seguinte:

<UserControl x:Class="Silverlight4_EF4.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="600" d:DesignWidth="650">
    <Grid x:Name="LayoutRoot" Background="Aqua">
        <Grid.RowDefinitions>
            <RowDefinition Height="60"></RowDefinition>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="100"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="Macoratti.net - SilverLight 4 com Entity Framework 4" FontSize="20" Margin="10,10,0,0"></TextBlock>
        <ListBox x:Name="lbCategorias" Height="400" Width="610" Grid.Row="1" HorizontalAlignment="Left" Background="Beige" Margin="10,10,0,10">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <StackPanel>
                        </StackPanel>
                        <StackPanel Margin="10" Height="50" Width="275">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding CategoriaNome}" FontSize="12" HorizontalAlignment="Left"  />
                                <TextBlock Text=", " FontSize="12" HorizontalAlignment="Left" />
                                <TextBlock Text="{Binding CategoriaDescricao}" FontSize="12" HorizontalAlignment="Left" />
                            </StackPanel>
                            <TextBlock Text="{Binding CategoriaNome}" FontSize="18" HorizontalAlignment="Stretch" Width="275"/>
                        </StackPanel>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <StackPanel Orientation="Horizontal" DataContext="{Binding SelectedItem, ElementName=lbCategorias}" Grid.Row="2" Margin="10,0,0,0">
            <StackPanel Width="79">
            </StackPanel>
            <StackPanel Margin="10" Height="100" Width="500">
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding CategoriaNome}" FontSize="12" HorizontalAlignment="Left"  />
                    <TextBlock Text=", " FontSize="12" HorizontalAlignment="Left" />
                    <TextBlock Text="{Binding CategoriaDescricao}" FontSize="12" HorizontalAlignment="Left" />
                </StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBox Text="{Binding CategoriaNome, Mode=TwoWay}" FontSize="18" HorizontalAlignment="Left" Width="275"/>
                    <Button x:Name="btnSalvar" Content="Salvar Alterações" Margin="10,0,0,0" Width="150" Height="30" Click="btnSalvar_Click"></Button>
                </StackPanel>
            </StackPanel>
        </StackPanel>
    </Grid>
</UserControl>

 

Estamos usando os controles TextBlock, ListBox e StackPanel para definir a interface desejada.

Agora temos que definir o código no arquivo code-behind MainPage.xaml.cs que irá efetivamente usar a classe, os métodos e o serviço definidos anteriormente.

Os namespaces usados são:

using System;

using System.Windows;

using System.Windows.Controls;

using System.Collections.ObjectModel;

using Silverlight4_EF4.CategoriaServiceReference;

A seguir vamos definir a variável Categorias do tipo ObservableCollection:

public ObservableCollection<CategoriaDTO> Categorias { get; set; }

No construtor MainPage() devemos ter:

  public MainPage()
   {
       InitializeComponent();
      CarregaCategorias();
   }

 

Onde a rotina CarregaCategorias(), cujo código vemos a seguir,  é acionada e usando o serviço WCF definido usa o método getCategorias() para retornar uma coleção de entidades Categoria cujo nome inicia coma letra V;

  private void CarregaCategorias()
  {
            CategoriaServiceClient cliente = new CategoriaServiceClient();
            cliente.GetCategoriasCompleted += new EventHandler<GetCategoriasCompletedEventArgs>(client_GetCategoriasCompleted);
            cliente.GetCategoriasAsync();
 }

O código do abaixo estamos atribuindo a coleção de Categorias obtidas ao evento ItemsSource do controle ListBox para exibir as informações sobre as Categorias na página MainPage.xaml;

 void client_GetCategoriasCompleted(object sender, GetCategoriasCompletedEventArgs e)
  {
            if (e.Error == null)
            {
                Categorias = e.Result;
                lbCategorias.ItemsSource = Categorias;
            }
 }

O código do evento Click do botão Salvar Alterações definido no arquivo MainPage.xaml salva as alterações usando método SaveCategoria usando o serviço WCF;

 private void btnSalvar_Click(object sender, RoutedEventArgs e)
{
            CategoriaServiceClient cliente = new CategoriaServiceClient();
            cliente.SaveCategoriaCompleted += new EventHandler<SaveCategoriaCompletedEventArgs>(cliente_SaveCategoriaCompleted);
            cliente.SaveCategoriaAsync((CategoriaDTO)((Button)sender).DataContext);
}

A seguir o código exibe a mensagem ao usuário:

  void cliente_SaveCategoriaCompleted(object sender, SaveCategoriaCompletedEventArgs e)
  {
            if (e.Error == null)
            {
                if (e.Result)
                {
                    MessageBox.Show("Alterações salvas com sucesso !");
                }
                else
                {
                    MessageBox.Show("Ocorreu um erro ao salvar as alterações.");
                }
            }
            else
            {
                MessageBox.Show(e.Error.Message);
            }
   }

Executando o projeto iremos obter:

Simples , simples assim...

Pegue o projeto completo aqui:   Silverligh4_EF4.zip

Eu sei é apenas SilverLight 4 , mas eu gosto...

Referências:

José Carlos Macoratti