sábado, 30 de novembro de 2013

Criar Modelo de dados EntityFramework e Serviços WCF a partir da Base de Dados

Neste artigo vamos ver como, tendo uma base de dados (BD) previamente criada, podemos obter o modelo de dados para o EntityFramework e um conjunto de serviços de dados WCF (Windows Communication Foundation) o qual pode depois ser usado por uma aplicação Web ou para obter dados da BD via OData.

O nosso exemplo, para uma aplicação de aluguer de automóveis, vai utilizar uma BD SQL Server com o seguinte esquema relacional:



Vamos, então, começar por criar um novo projeto, no Visual Studio 2012, de tipo WCF Service Application (damos-lhe o nome WcfRentACarService):



Este tipo de projeto cria automaticamente uma classe Service1 dentro de um namespace com o mesmo nome do projeto (WcfRentACarService):



Inicialmente, a estrutura do nosso projeto é, então, a seguinte:


Vamos, agora, criar o modelo de mapeamento objeto relacional EntityFramework, correspondente à BD que já temos (ver esquema acima), o qual vai servir para fazer toda a interação com a BD e para gerar os serviços de dados que queremos expor para o exterior.
Fazemos, no nosso projeto, Add --> New Item, e escolhemos criar um ADO.NET Entity Data Model:


Selecionamos gerar o modelo a partir da BD:

Configuramos a ligação à BD:



E selecionamos os objetos a mapear, e o nome do namespace do modelo:
(Nota: também selecionei a opção para pluralizar os nomes das coleções de entidades e singularizar o nome de uma entidade...)

E o resultado é o modelo RentACarModel.edmx, cuja visão diagramática é:

Depois, queremos criar um serviço de dados OData, para disponibilizar o CRUD gerado pelo EntityFramework num endpoint Http (na verdade, atualmente, em OData, apenas as consultas ficam disponíveis). Selecionamos ADD --> New Item e o tipo de item WCF Data Service:



Isto, cria o seguinte ficheiro/classe:


O qual devemos alterar como se segue, para disponibilizar os serviços de dados requeridos:

Ficheiro WcfRentACarDataService.svc.cs:

using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;

namespace WcfRentACarService
{
    public class WcfRentACarDataService : DataService<Rent_a_CarEntities>
 {
   // This method is called only once to initialize service-wide policies.
   public static void InitializeService(DataServiceConfiguration config)
   {
      // TODO: set rules to indicate which entity sets and 
      //       service operations are visible, updatable, etc.
      // Examples:
      config.SetEntitySetAccessRule("*"
                          EntitySetRights.AllRead);
      config.SetServiceOperationAccessRule("*"
                          ServiceOperationRights.All);
      config.DataServiceBehavior.MaxProtocolVersion = 
                          DataServiceProtocolVersion.V3;
   }
 }
}

Ficheiro Web.config resultante:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </assemblies>
    </compilation>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false before deployment -->
          <serviceMetadata httpGetEnabled="true" />
          <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <!--
        To browse web app root directory during debugging, set the value below to true.
        Set to false before deployment to avoid disclosing web app folder information.
      -->
    <directoryBrowse enabled="true" />
  </system.webServer>
  <connectionStrings>
    <add name="Rent_a_CarEntities" connectionString="metadata=res://*/RentACarModel.csdl|res://*/RentACarModel.ssdl|res://*/RentACarModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=Rent_a_Car;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
</configuration>


Agora, se corrermos a aplicação (ou ViewIn Browser, sobre o Data Service), vai aparecer-nos a lista de operações de Collections que podemos consultar via Http:



Claro que o objetivo não é usar o serviço a partir do Browser, mas sim a partir de um cliente como por exemplo o Excel ou uma aplicação Web desenvolvida para usar os nossos serviços.
De qualquer forma, aqui ficam os screenshots da execução do serviço de consulta de Cars:


O OData expõe recursos de dados em endereços HTTP. O caminho dos recursos é baseado nos relacionamentos entre entidades do Entity Data Model (Entity Framework). O modelo exemplo usado neste artigo, tem como entidades do domínio aplicacional, Cars, Customers e Rentings.
Essas entidades são expostas em OData como recursos de Coleção de instâncias, os quais são, no nosso exemplo, acessíveis através de:


  • Todas as Viaturas (Cars):  http://localhost:25408/WcfRentACarDataService.svc/Cars
  • A Viatura com ID = 1:  http://localhost:25408/WcfRentACarDataService.svc/Cars(1)
  • Os alugueres (rentings) da viatura com ID = 1:  http://localhost:25408/WcfRentACarDataService.svc/Cars(1)/Rentings

E assim por diante...


A disponibilização dos serviços em JSON e como consumir os serviços numa aplicação Web (HTML & Javascript) ficam para os próximos artigos.


Referências:

Artigos relacionados:



Sem comentários:

Enviar um comentário