.NET

29 out, 2009

.NET – Consumindo um serviço WCF com acesso a dados via LINQ to SQL

Publicidade

Neste artigo eu vou mostrar como
usar um serviço com acesso a dados com LINQ to SQL para
consultar um banco de dados SQL Server.
Eu vou usar como exemplo neste artigo o banco de dados Macoratti.mdf e vou trabalhar com a tabela
Categories.

O banco de dados Macoratti.mdf é uma réplica
simplificada do banco de dados Northwind.mdf e possui a estrutura
exibida na figura abaixo. Em detalhes vemos a tabela Categorias com os seus
campos e alguns dados informados:

O objetivo é reforçar os conceitos do WCF e mostrar
uma forma simples de usar um serviço WCF sendo consumido por uma aplicação
Windows Forms com LINQ To SQL.

Para realizar tal tarefa irei criar
uma solução contendo 3 projetos assim descritos:

  • ServicoWCF – Projeto contendo o serviço WCF onde iremos definir um contrato que descreve a tarefa que o serviço vai expor através do contrato; (O contrato é uma interface que contém as assinaturas dos métodos que serão expostos. A interface deverá ser decorada com o atributo:ServiceContract)

      – GetDataCategorias() – que irá acessar a tabela Categorias e retornar todos os seus dados;

  • DAL_Linq – Projeto class Library que atuará como uma camada de acesso a dados usando LINQ to SQL;

    – Geração do mapeamento ORM da tabela Categorias para a entidade Categorias;

  • WindowsConsomeWCF – Projeto Windows Forms que irá consumir o serviço acessando e exibindo os dados;

    – Utilização de um controle DataGridView em um formulário para exibir as categorias da tabela Categorias ;

Apenas para relembrar, cada serviço, para ser
exposto através do WCF, precisa atender os seguintes requisitos:

  • Possuir um contrato e a sua implementação
    concreta;
  • Possuir um configuração de Binding; (configuração
    de como um EndPoint de um serviço WCF se comunica com outros EndPoints)
  • Possuir ao menos um  EndPoint; (define
    como as funcionalidades do WCF serão acessadas)

Estes requisitos são conhecidos como ABC:
um
serviço tem que ter um endereço de Endpoint (Address), um Binding
e um Contrato.

Uma coisa que eu não mencionei no artigo anterior
foram as configurações de Binding fornecidas pela infra-estrutura WCF.

O Binding é responsável por indicar como a
comunicação vai ser feita com um endpoint, qual o transporte será usado (HTTP,TCP,
etc.), qual a codificação vai ser usada (Texto
ou Binário) para serializar as mensagens, transações, segurança, etc.

A seguir temos as principais configurações de Binding que podem ser
usadas conforme a utilização e a definição de como será hospedada o seu serviço
WCF:

Nome Protocolo Definição
BasicHTTPBinding HTTP – Usa o protocolo HTTP para
as comunicações como meio de transporte, sendo que as mensagens são definidas
em XML como os Web Services.
– O modo de transferência pode ser Streaming ou Buffered, sendo a
última o default.
– Não dá suporte a transações;
– Segurança: None, Transport, Message e Mixed. None é a default.
WSHTTPBinding HTTP -Idêntico ao
BasicTTPBinding só que permitindo mais recursos, como transações,
segurança na mensagem enviada, etc.
– O modo de transferência Buffered.
– Dá suporte a transações;
– Segurança: None, Transport, Message e Mixed. Message é a default. 
NetTCPBinding TCP -Usa o protocolo TCP
para as comunicações; as mensagens são codificadas no formato binário;
NetNamedPipeBinding Windows Named Pipe -Usa o protocolo
Windows Named Pipe para as comunicações; as mensagens são definidas no
formato binário; É usado para cenários onde o host e o cliente estão
hospedados na mesma máquina.
– Não dá suporte a transações;
– Transporte IPC;

Obs: Ainda existe a
possibilidade de você customizar o seu Binding usando a classe CustomBinding.

Esta definição pode ser feita no arquivo web.config.
Veja abaixo um exemplo de um arquivo web.config exibindo a configuração
do Binding:

Neste exemplo o endereço
do endpoint está vazio (
<endpoint
address=””
), permitindo que IIS use o endereço padrão.

.........
<services>

<service name="ServicoWCF.Service1" behaviorConfiguration="ServicoWCF.Service1Behavior">

<!-- Service Endpoints -->

<endpoint address="" binding="wsHttpBinding" contract="ServicoWCF.IService1">

<!--

Upon deployment, the following identity element should be removed or replaced to reflect the

identity under which the deployed service runs. If removed, WCF will infer an appropriate identity

automatically.

-->

<identity>

<dns value="localhost"/>

</identity>

</endpoint>

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

</service>

</services>
......

Eu vou usar o Visual Studio 2008 SP1 para criar a
solução deste artigo.

Criando a solução e os
projetos

Abra o Visual Studio 2008 SP1
(se você não tiver
o VS 2008, pegue a versão trial por 90 dias
aqui) e no menu File selecione New Project ou clique diretamente em Create Project;

Na janela New Project selecione : Other Project
Types e a seguir Visual Studio Solutions e, em Templates, selecione
Blank Solution
e informe o nome Usando_LINQ_WCF e escolha a localização do projeto;

Vamos agora incluir o projeto do tipo Class Library
chamado DAL_Linq que será a nossa camada de acesso a dados onde iremos usar o LINQ to SQL.

No menu File selecione selecione Add e a seguir New
Project;

Na janela Add New Project selecione Visual Basic,
e, em
Templates, selecione Class Library e informe o nome DAL_Linq e clique em
OK;

Agora vamos incluir outro projeto, o projeto WCF,
onde iremos definir o serviço que iremos consumir. Iremos usar o template
WCF Service Application que já fornece a infra-estrutura básica para usar
o serviço.

No menu File selecione selecione Add e a seguir New
Project;

Na janela Add New Project selecione Web, e, em
Templates, selecione
WCF Service Application, informe o nome ServicoWCF e clique
em OK;

Por último vamos incluir um projeto
Windows Forms
que irá consumir o serviço criado no WCF.

No menu File selecione selecione Add e a seguir New
Project;

Na janela Add New Project selecione Windows
e, em Templates, selecione Windows Forms Application informe o nome WindowsConsumeWCF e clique em OK;

Ao final desta etapa a sua solução deverá exibir na
janela Soluction explorer os seguintes projetos:

Definindo a camada de
acesso a dados – DAL_Linq

Vamos definir a camada de acesso a dados usando o
LINQ to SQL. Para isso vamos excluir a classe class1.vb criada por padrão. Feito
isso vamos verificar se existe uma conexão com o banco de dados que desejamos
usar. Neste exemplo eu vou usar o banco de dados Macoratti.mdf.

Abra o Server Explorer e se a conexão com o banco
de dados não aparecer na janela, clique em Add Connection e informe o nome do
servidor e selecione o Banco de dados Macoratti.mdf ou outro que você quiser usar e
clique em OK;

Agora  vamos clicar com o botão direito do
mouse sobre o nome do projeto e selecionar a opção Add New Item;

Selecione o template LINQ to SQL Classes
e informe
o nome Categorias.dbml e clique em Add;

Abra a janela Server Explorer, expanda os objetos
do banco de dados Macoratti.mdf e arraste e solte a tabela Categorias no
descritor LINQ para criar a entidade Categoria. Neste momento será criado o
mapeamento OR/M. Observe que foi criado o DataContext
CategoriasDataContext.

Selecione a propriedade Serialization Mode
do DataContext e defina o seu valor como Unidirectional,
com isso teremos a serialização requerida pelo serviço WCF.
Feito isso, salve o projeto.

Definindo o serviço WCF
em : ServicoWCF

Para definir o serviço WCF, primeiro temos que
incluir uma referência ao nosso projeto DAL_Linq. Clique com o botão direito do
mouse sobre o projeto ServicoWCF e selecione Add Reference;

Na janela Add Reference selecione a guia Projects,
selecione DAL_Linq e clique em OK;

Abra o arquivo de interface IService1.vb e remova
todo o código existente. A seguir inclua o código que define o método
GetDataCategorias() que retorna uma Lista de Categorias do tipo
DAL_Linq.Categoria;

Observe que os atributos <ServiceContratct()> e <OperationContract()> são obrigatórios para definir o contrato do serviço. O
atributo ServiceContract serve para indicar que a interface é um serviço
WCF e o atributo OperationContract indica que o método será exportado e
estará visível para os clientes do serviço.

Agora temos que implementar o método definido na
interface no arquivo Service1.svc. Selecione o arquivo e remova todo o código
existente definindo o código conforme mostrado na figura abaixo:

Obs: Você terá que incluir uma
referência a System.Data.Linq
neste projeto.

O método GetDataCategorias retorna uma
coleção de Categorias usando uma consulta LINQ. Após isso, salve o projeto.

Consumindo o serviço em
uma aplicação Windows Forms: WindowsConsomeWCF

Vamos agora criar uma interface simples incluindo
um controle DataGridView no formulário form1.vb do
projeto WindowsConsomeWCF;

Inclua um controle DataGridView-
gdvCategorias e um controle Button –
btnExibir conforme a figura abaixo:

Feito isso, clique com o botão direito do mouse
sobre o projeto Windows e selecione a opção Add  Service Reference;

Clique no botão Discover e selecione
Services in Solution;

Ocorrendo tudo como previsto, o serviço que criamos
será encontrado e exibido na janela Services;

Clique no serviço Service1.svc
e o método GetDataCategorias() será exibido na janela Operations;

Podemos alterar o nome do namespace sugerido,
mas eu vou usar o nome indicado: ServiceReference1;

Antes de encerrar, precisamos efetuar um pequeno
ajuste. Clique no botão Advanced… e altere o tipo de dados para
System.Collections.Generic.List, pois este é o tipo
de dados que será retornado pelo nosso serviço.

Após isso, clique em OK;

Você deverá ver no seu projeto
WIndows Forms a referência ao serviço criada conforme a figura abaixo:

Agora vamos usar o serviço incluindo no evento
Click do botão Exibir Categorias o seguinte código:

O código é simples, estou criando uma instância do
meu serviço definido em ServiceReference1;

A seguir estou acessando o método
getDataCategorias(), definido no serviço que retorna uma coleção de
categorias e exibindo no controle
DataGridView.

O resultado pode ser visto na figura abaixo:

Com isso concluímos a nossa primeira aplicação que
consome um serviço WCF com acesso a dados usando o LINQ to SQL.

Pegue a solução completa aqui: 
Usando_LINQ_WCF.zip

E o banco de dados aqui: Macoratti.mdf

Eu sei, é apenas WCF e LINQ, mas eu
gosto…