Arquiteto de Soluções
Microsoft Brasil
Resumo
Uma das principais tendências para a construção de arquiteturas de soluções é o modelo Software + Serviço. Esse tipo de arquitetura aproveita o poder de processamento local e as funcionalidades de aplicações e sistemas publicados como serviços através da internet. Nesse contexto, encontramos diversos cenários possíveis como web services corporativos, serviços para intranets, serviços para aplicações web 2.0, etc., assim como conceitos como barramentos de serviços, arquiteturas SaaS (Software as a Service), arquiteturas orientadas a serviço (Service Oriented Architecture) e aplicações compostas (Composite Applications).
No modelo Software + Serviço destacamos a composição de funcionalidades, onde uma solução pode consumir serviços locais ou serviços publicados na nuvem. Da mesma forma, uma solução pode consumir dados persistidos localmente, assim como dados persistidos em repositórios virtuais, a partir da internet.
Este artigo apresenta dois componentes importantes para uma arquitetura Software + Serviço sobre a plataforma Microsoft: o SQL Server Data Services (SSDS), um serviço oferecido pela Microsoft para a persistência de dados na nuvem, funcionando como um repositório virtual na internet; e o framework ADO.NET Data Services, que oferece um mecanismo para publicação de dados e navegação através de interfaces web para nossas soluções corporativas.
Quando pensamos nas diversas opções de integração entre sistemas, surge uma lista enorme de tecnologias e arquiteturas que historicamente conectaram nossas organizações nos últimos anos. Desde os modelos puramente baseados em chamadas RPC – Remote Pocedure Call, passando por servidores TCP multi-thread, objetos distribuídos, componentes COM, Web Services, padrões e protocolos para internet, etc., até as mais recentes organizações de software como serviços do SaaS e do SOA. De fato, um universo de tecnologias e combinações está a nossa disposição hoje em dia.
Envolvendo grande parte dessa evolução encontramos a chamada “computação na nuvem”, que dentro da estratégia Microsoft é conhecida como visão Software + Serviço (Software+Services). A essência dessa visão está em conceber aplicações que consomem dados locais e serviços locais, assim como dados remotos e serviços remotos, publicados em provedores (hosters) ou datacenters diversos e geograficamente distribuídos. Como resultado, esse tipo de arquitetura fornece uma solução que é capaz de aproveitar tanto o poder de processamento da estação local ou do equipamento móvel (o “software”), como a capilaridade e a escalabilidade de diversos serviços online distribuídos e oferecidos pelo mercado, a partir da nuvem (o “serviço”). Um dos pontos fortes desse tipo de arquitetura é o poder de composição de funcionalidades de diferentes fontes de dados e serviços, criando um mix de recursos com o melhor de cada mundo (por exemplo, os mundos web, mobile, desktop e enterprise).
Nesse contexto, vamos falar especificamente sobre um dos componentes básicos dessa nova realidade: a publicação e o consumo de dados da nuvem. O projeto Microsoft conhecido como “Sitka” corresponde a um dos serviços online da Microsoft, destinado a publicação de dados na nuvem. Nesse cenário, dados armazenados no serviço “Sitka” serão persistidos em um dos vários datacenters da Microsoft espalhados pelo mundo. Ao mesmo tempo, o projeto conhecido como “Astoria” oferece ao desenvolvedor a mesma funcionalidade de publicação e consumo de dados na nuvem no ambiente corporativo, permitindo que bancos de dados sejam publicados através de interfaces web, de um modo rápido e flexível, usando serviços WCF – Windows Communication Foundation com protocolos SOAP ou REST.
Para começar, vejamos um pouco de história: quando pensamos nos anos 80, era importante se ter a aplicação e a base de dados muito próximos um do outro. Nesse cenário, o consumo de dados era imediato e personalizado, de tal modo que a aplicação era construída de forma muita acoplada ao modelo de dados. Já no final dos anos 80 surge o modelo Cliente/Servidor, onde um servidor dedicado para os dados fornecia serviços para o mundo externo. Clientes consumiam os dados através de bibliotecas de acesso, o que fornecia uma maior facilidade para o desenvolvimento de aplicações, com um baixo acoplamento. Havia também protocolos de aplicação entre cliente e servidor, através dos quais consultas SQL (queries) eram trafegadas. Veja que nesse modelo a aplicação precisava ser construída pensando nas consultas, nas atualizações possíveis, no tempo de rede, etc., o que trouxe um grande desafio para as primeiras soluções.
Ao longo dos anos, esse mesmo modelo tem sido evoluído e se tornado mais complexo. Além de múltiplos protocolos entre clientes e servidores, existem agora diferentes middlewares de acesso, níveis de estruturas de dados, múltiplas camadas, diferentes mecanismos de apresentação, como dispositivos móveis, desktops, portais web, mashups, workflows, webparts, etc.
Na última década, observamos diversas opções de arquiteturas sendo utilizadas no ambiente corporativo, evoluindo os conceitos de serviços, clientes e servidores. Modelos como EDI – Electronic Data Interchange, EAI – Enterprise Application Integration, SOA – Service Oriented Architecture, SaaS – Software as a Services e Aplicações Compostas tornaram-se ferramentas importantes na evolução da infra-estrutura de TI. Mais recentemente, vimos o nascimento de conceitos como negócio ágil (agile business), negócio orientado a serviços e computação orientação a serviços, como exemplos de uma integração entre TI e o negócio da empresa cada vez mais forte. Finalmente, novas forças motivadoras surgiram nesses últimos anos, como o elevado poder de processamento de chips multi-núcleos (encapsulando diversas CPU’s numa mesma pastilha) e um número crescente de datacenters pelo mundo, facilitando a criação de um ambiente frutífero para a publicação e oferta de serviços através da internet. Nesse contexto surgiu a visão Software + Serviços.
Uma arquitetura que contempla o modelo Software + Serviço (ou simplesmente S+S) pode operar diferentes combinações de funcionalidades, locais e remotas, de acordo com a qualidade de cada serviço disponível. Isso significa que uma solução S+S pode contemplar situações off-line e on-line, o que determina momentos de processamento local e remoto, enquanto completa uma tarefa. Desse modo, podemos classificar tipos diferentes de serviços e funcionalidades que participam dessa arquitetura. Essa classificação será importante para determinar o nível de integração e qualidade de serviço que será oferecido, assim como quais tipos serão ferramentas para a construção de novos serviços e funcionalidades para nossa solução.
A figura abaixo apresenta uma classificação dos serviços do S+S de acordo com a sua utilização, veja:

Figura 1 – Tipos de serviços de uma arquitetura Software + Serviço.
Finished Services
| • | O primeiro grupo é conhecido como serviços terminais ou Finished Services. São serviços usados principalmente por usuários finais (end-users). Como exemplos de serviços Finished Services encontramos diversas ofertas publicadas pela Microsoft, como o Exchange Online, o SharePoint Online, o Office Communications Online e o Office Live Meeting, entre outros. Todos esses serviços oferecem funcionalidades de alto nível na arquitetura Software + Serviço, estando prontos para utilização e consumo imediato. Para saber mais sobre esses serviços, confira o link http://www.microsoft.com/online/. |
Attached Services
| • | O segundo grupo são os chamados Attached Services ou serviços anexos. Eles adicionam valor quando usados em conjunto com o software local (on-premise), instalado no desktop ou no ambiente da empresa. São usados principalmente por profissionais de TI (IT-Pros) e alguns exemplos são o conhecido Windows Update e o Exchange Hosted Services, este último oferecendo recursos como anti-spam, anti-virus, criptografia para Exchange sobre a internet, etc. De fato, são componentes cada vez mais utilizados em infra-estruturas de serviços no ambiente corporativo. |
Building Blocks Services
| • | Finalmente, temos os Building Blocks Services ou blocos construtivos de serviços. Esses componentes são usados principalmente por desenvolvedores para a construção de todos os tipos de serviços que constituem uma arquitetura S+S. Entre os exemplos mais citados temos o Microsoft LiveID, o Microsoft BizTalk Services, o SQL Server Data Services, o Sync Services, entre outros. |
O projeto conhecido pelo codinome “Sitka” é na verdade a Microsoft® SQL Server® Data Services (ou SSDS), um dos vários serviços online sendo disponibilizados pela Microsoft. Esse serviço pode ser definido como um repositório de dados virtual na nuvem, acessado através de uma interface REST/SOAP, com segurança SSL. De fato, o SSDS será um serviço da plataforma Microsoft OnLine Services sendo um grande exemplo de um Building Block Service, como definido anteriormente. O SSDS é baseado em tecnologia Microsoft® SQL Server® e deve ser um dos Building Block Service mais importantes num futuro próximo.
Os repositórios SSDS estarão fisicamente em um dos vários datacenters da Microsoft na América do Norte, na Europa ou na Ásia, permitindo um controle de acesso agrupado por geografias e distribuição. Para pequenas e médias empresas, será uma solução de baixo custo para o controle e armazenamento de informações através de uma interface Web. Os preços de utilização e políticas de licenciamento ainda estão em definição. Atualmente, o SSDS está em programa Beta, sendo testado por diversas empresas convidadas pela Microsoft. Para saber mais sobre esse serviço e participar do programa Beta público, você precisa se registrar através do link http://www.microsoft.com/sql/dataservices/
O serviço SSDS será parte da plataforma de dados da Microsoft, oferecendo assim mais uma alternativa de composição para aplicações Software + Serviços. As diversas funcionalidades presentes no ambiente SQL local, como integração, análise, construção de relatórios, serviços de busca, consultas, sincronização, etc., deverão ser gradativamente oferecidos como funcionalidades de serviços online do SSDS. A figura a seguir apresenta esse mapa da plataforma de dados Microsoft, destacando o SSDS como uma nova opção na nuvem:

Figura 2 – Funcionalidades da plataforma de dados Microsoft e o SQL Server Data Services.
Para a organização dos dados, o SSDS utiliza 3 elementos importantes: Authority, Container e Entity. Esses elementos são conhecidos como conceitos “ACE”.
O conceito Authority será responsável pela unidade de geo-localização e cobrança pela utilização dos dados. Através dele, será para possível organizar bancos de dados por geografia, agrupando coleções de containers por afinidades.
O conceito Container será a unidade básica de consistência e busca sobre os dados armazenados. Um container poderá agrupar coleções de entidades, que são de fatos as propriedades e valores dos dados persistidos.
Finalmente, o conceito Entity será a unidade básica de atualização e operação sobre os dados armazenados. Persistidos através de pacotes nome/valor, permitirão a inclusão de dados estruturados e não estruturados, de acordo com a necessidade da aplicação.
O acesso físico aos dados ocorre através de uma URI – Universal Resource Identifier, uma chamada feita para os Web Services do serviço SSDS, onde os valores Authority, Container e Entity são apresentados, num formato de busca REST – REpresentational State Transfer. De fato, o serviço SSDS é um serviço compatível com os padrões Web 2.0, permitindo uma integração total com esse tipo de aplicação.
Desse modo, algumas características são importantes, como:
| • | Acesso usando endpoints SOAP ou REST; |
| • | Os Endpoint usam segurança SSL; |
| • | Os recursos são acessados via URI's; |
| • | Todo recurso ou entidade possui uma URI para identificação e acesso; |
| • | Os 4 verbos são usados para transferir representações de recursos, isto é, GET, PUT, DELETE, POST; |
| • | As transações são stateless (sem estado), como uma característica importante no acesso; |
| • | As chamadas REST permitem o consumo de dados a partir de servidores diferentes do host do front-end; |
| • | O serviço ainda suportará operadores sobre as consultas REST. |
Uma chamada de dados completa para o serviço SSDS pode ser representada como vemos a seguir:

Figura 3 – Exemplo de chamada para o consumo de dados persistidos no serviço SQL Server Data Services (SSDS).
Na figura 4, note que cada entidade possui uma URI bem definida, uma das grandes características do modelo REST para Web. Assim, nosso cliente deve consumir essa API web do mesmo modo em que consome um web services qualquer, passando o caminho para obter ou manipular uma entidade desejada.
O serviço SSDS implementa uma série de operações para a criação, remoção, busca e atualização dos valores para Authotiry, Container e Entity. Para a execução dessas operações, o cliente pode implementar chamadas através de SOAP ou REST, conforme a necessidade. Para melhor ilustrar a aplicação dos serviços SSDS, vejamos um exemplo genérico a seguir.
Antes da publicação de nossos dados no serviço SSDS, precisamos criar os elementos de organização de dados, ou seja, os conceitos "ACE" precisam ser criados e atualizados através de chamadas SOAP ou REST, para que então possamos atualizar nossos dados no formato de entidades.
O primeiro passo é criar uma aplicação qualquer no Visual Studio para consumir o serviço SSDS. Para consumir o serviço adicionamos uma Service Reference, do mesmo modo quando consumimos um serviço qualquer. Assim, para adicionar uma Service Reference no Visual Studio podemos fazer:
| • | Clicar Add Service Reference a partir do menu de projeto criado; |
| • | Especificar o endereço http://data.beta.mssds.com/soap/v1?wsdl, por exemplo; |
| • | Mudar o valor default do ServiceReference1 para o namespace SitkaClient. |
| • | Entrar com o código para criação de Authority, Container e Entity, como veremos a seguir; |
| • | Compilar e executar a aplicação; |
A figura a seguir apresenta os métodos disponíveis com o serviço “Sitka” referenciado acima:

Figura 4 – Métodos disponíveis no serviço SSDS beta, para testes.
Vejamos alguns exemplos de código para a criação de Authority, Container e Entity, através de chamadas SOAP, lembrando que podemos utilizar chamadas REST como alternativa. A idéia será criar um banco de dados para informações sobre livros. Iremos criar uma Authority chamada “books-docsamples” e depois, faremos a inclusão dos dados de alguns livros.
Para a criação de uma Authoriry, devemos criar um escopo de serviço, que será usado para as demais operações de atualização e criação de elementos. para acessar o serviço apesentamos as credenciais do usuário, assinante do serviço SSDS.
A partir da criação do escopo, podemos criar efetivamente uma Authoriry (“books-docsamples”), como vemos a seguir:
Listagem 1. Método para criação de uma Authority.
public void CreateAuthorityUsingSOAP()
{
using (SitkaSoapServiceClient proxy = new SitkaSoapServiceClient())
{
proxy.ClientCredentials.UserName.UserName = userName;
proxy.ClientCredentials.UserName.Password = password;
Scope serviceScope = new Scope();
Authority auth = new Authority();
auth.Id = authorityId;
try
{
proxy.Create(serviceScope, auth);
Console.WriteLine("Authority {0} criada!", auth.Id);
}
catch (FaultException<Error> e)
{
if (e.Detail.StatusCode != ErrorCodes.EntityExists)
{
Console.WriteLine("Error: {0}:{1}", e.Detail.StatusCode, e.Detail.Message);
Console.WriteLine(e);
return;
}
Console.WriteLine("Authority {0} já existe!", auth.Id);
}
}
}
Com a criação do escopo e da Authority, podemos criar o container para nossos dados, conforme listagem a seguir:
Listagem 2. Método para criação de um Container.
public void CreateContainerUsingSOAP()
{
using (SitkaSoapServiceClient proxy = new SitkaSoapServiceClient())
{
proxy.ClientCredentials.UserName.UserName = userName;
proxy.ClientCredentials.UserName.Password = password;
Scope myAuthorityScope = new Scope();
myAuthorityScope.AuthorityId = authorityId;
Container c1 = new Container();
c1.Id = containerId;
try
{
proxy.Create(myAuthorityScope, c1);
Console.WriteLine("Container {0} criada!", c1.Id);
}
catch (FaultException<Error> e)
{
if (e.Detail.StatusCode != ErrorCodes.EntityExists)
{
Console.WriteLine("Error: {0}:{1}", e.Detail.StatusCode, e.Detail.Message);
Console.WriteLine(e);
return;
}
Console.WriteLine("Container {0} já existe!", c1.Id);
}
}
}
A partir da criação da Authority e Container, podemos criar nossas entidades, persistindo assim nossas informações no serviço SSDS. O trecho a seguir exemplifica a gravação de dados no serviço através das entidades:
Listagem 3. Método para criação de Entities.
public void CreateEntityUsingSOAP()
{
using (SitkaSoapServiceClient proxy = new SitkaSoapServiceClient())
{
proxy.ClientCredentials.UserName.UserName = userName;
proxy.ClientCredentials.UserName.Password = password;
Scope myContainerScope = new Scope();
myContainerScope.AuthorityId = authorityId;
myContainerScope.ContainerId = containerId;
// Vamos criar aqui uma entidade livro.
Entity e1 = new Entity();
// Definindo o metadado da propriedade.
e1.Id = Guid.NewGuid().ToString() + "_MySampleBook";
e1.Kind = "UsedBookKind";
e1.Properties = new Dictionary<string, object>();
e1.Properties["Title"] = "My Book";
e1.Properties["ISBN"] = "1-57880-066-36";
e1.Properties["Author"] = "Mr. Author";
e1.Properties["Publisher"] = "Mr. Publisher";
e1.Properties["InPrint"] = false;
e1.Properties["NumberOfCopiesSold"] = 250m;
e1.Properties["PublicationDate"] = DateTime.Parse("01/27/2004");
e1.Properties["CoverPhoto"] = new byte[] { 0x1, 0x2, 0x3 };
try
{
proxy.Create(myContainerScope, e1);
Console.WriteLine("Entity {0} criada!", e1.Id);
}
catch (FaultException<Error> e)
{
if (e.Detail.StatusCode != ErrorCodes.EntityExists)
{
Console.WriteLine("Error: {0}:{1}", e.Detail.StatusCode, e.Detail.Message);
Console.WriteLine(e);
return;
}
Console.WriteLine("Entity {0} já existe!", e1.Id);
}
}
}
A partir do trecho acima, notamos que uma entidade não é fortemente tipada, como temos em bases de dados relacionais. Uma entidade é a menor unidade de armazenamento no SSDS, baseando-se num escalar definido como nome/tipo/valor. Assim, estamos trabalhando com um metadado para cada valor armazenado no SSDS. Veja o trecho abaixo onde o metadado é definido:
Listagem 4. Definindo o metadado para a criação de uma entidade.
Uma aplicação usuária do serviço SSDS poderá implementar os métodos para a criação, deleção e atualização dos elementos Authority, Container e Entity, como sugerido a seguir:
Métodos usando REST
| • | CreatingAuthorityUsingREST |
| • | CreatingContainerUsingREST |
| • | DeletingContainerUsingREST |
| • | CreatingEntityUsingREST |
| • | UpdatingEntityUsingREST |
| • | DeletingEntityUsingREST |
Métodos usando SOAP
| • | CreatingAuthorityUsingSOAP |
| • | CreatingContainerUsingSOAP |
| • | DeletingContainerUsingSOAP |
| • | CreatingEntityUsingSOAP |
| • | UpdatingEntityUsingSOAP |
| • | DeletingEntityUsingSOAP |
Uma listagem completa da classe para criação dos métodos e consumo do serviço SSDS é dada a seguir:
Listagem 5. Exemplo de classe cliente para o serviço SSDS usando interface SOAP.
using System;
using System.Collections.Generic;
using System.Text;
using System.ServiceModel;
using System.IO;
using SOAPClientToSSDS.SitkaClient;
namespace SOAPClientToSSDS
{
class Program
{
private const string userName = "YourUserId";
private const string password = "YourPassword";
private const string authorityId = "YourExistingAuthorityId";
private const string sampleContainerId = "BookContainer_ForQueries";
private static SitkaSoapServiceClient proxy = null;
static void Main(string[] args)
{
using (proxy = new SitkaSoapServiceClient())
{
proxy.ClientCredentials.UserName.UserName = userName;
proxy.ClientCredentials.UserName.Password = password;
CreateContainer();
AddEntities();
ExecuteGET();
DeleteContainer();
}
}
private static void CreateContainer()
{
Scope myAuthorityScope = new Scope();
myAuthorityScope.AuthorityId = authorityId;
Container c1 = new Container();
c1.Id = sampleContainerId;
try
{
proxy.Create(myAuthorityScope, c1);
Console.WriteLine("Container {0} criado!", c1.Id);
}
catch (FaultException<Error> e)
{
if (e.Detail.StatusCode != ErrorCodes.EntityExists)
{
Console.WriteLine("Error: {0}:{1}", e.Detail.StatusCode, e.Detail.Message);
Console.WriteLine(e);
return;
}
Console.WriteLine("Container {0} já existente!", c1.Id);
}
}
private static void AddEntities()
{
Scope myContainerScope = new Scope();
myContainerScope.AuthorityId = authorityId;
myContainerScope.ContainerId = sampleContainerId;
// Boook 1
AddEntity(myContainerScope,
"MySampleBook1", "ChildrensBook",
"My first book", "1-57880-066-1", "Mr. Author1",
"Mr. Publisher1", true, 250, "01/27/2007");
// Boook 2
AddEntity(myContainerScope,
"MySampleBook2", "TechnicalBook",
"My second book", "1-57880-066-2", "Mr. Author1",
"Mr. Publisher2", false, 999, "01/26/2006");
// Boook 3
AddEntity(myContainerScope,
"MySampleBook3", "ChildrensBook",
"My third book", "1-57880-066-3", "Mr. Author2",
"Mr. Publisher1", true, 2000, "01/25/2005");
}
private static void AddEntity(Scope myContainerScope,
string inputId, string inputKind, string inputTitle,
string inputISBN, string inputAuthor, string inputPublisher, bool inputInPrint,
decimal inputCopiesSold, string inputPubDate)
{
Entity e1 = new Entity();
e1.Id = inputId;
e1.Kind = inputKind;
e1.Properties = new Dictionary<string, object>();
e1.Properties["Title"] = inputTitle;
e1.Properties["ISBN"] = inputISBN;
e1.Properties["Author"] = inputAuthor;
e1.Properties["Publisher"] = inputPublisher;
e1.Properties["InPrint"] = inputInPrint;
e1.Properties["NumberOfCopiesSold"] = inputCopiesSold;
e1.Properties["PublicationDate"] = DateTime.Parse(inputPubDate);
e1.Properties["CoverPhoto"] = new byte[] { 0x1, 0x2, 0x3 };
try
{
proxy.Create(myContainerScope, e1);
Console.WriteLine("Entity {0} criada!", e1.Id);
}
catch (FaultException<Error> e)
{
if (e.Detail.StatusCode != ErrorCodes.EntityExists)
{
Console.WriteLine("Error: {0}:{1}", e.Detail.StatusCode, e.Detail.Message);
Console.WriteLine(e);
return;
}
Console.WriteLine("Entity {0} já existente!", e1.Id);
}
}
private static void ExecuteGET()
{
Scope myAuthorityScope = new Scope();
myAuthorityScope.AuthorityId = authorityId;
Authority auth = (Authority)proxy.Get(myAuthorityScope);
Console.WriteLine("Id: {0}, Version: {1}", auth.Id, auth.Version);
Scope myContainerScope = new Scope();
myContainerScope.AuthorityId = authorityId;
myContainerScope.ContainerId = sampleContainerId;
Container myContainer = (Container)proxy.Get(myContainerScope);
Console.WriteLine("Id: {0}, Version: {1}", myContainer.Id, myContainer.Version);
Scope myEntityScope = new Scope();
myEntityScope.AuthorityId = authorityId;
myEntityScope.ContainerId = sampleContainerId;
myEntityScope.EntityId = "MySampleBook1";
Entity book = proxy.Get(myEntityScope);
Console.WriteLine("Id: {0}, Version: {1} Kind: {2}", book.Id, book.Kind, book.Version);
foreach (KeyValuePair<string, object> p in book.Properties)
{
Console.WriteLine("{0}: \t{1}", p.Key, p.Value);
}
}
private static void DeleteContainer()
{
Scope myContainerScope = new Scope();
myContainerScope.AuthorityId = authorityId;
myContainerScope.ContainerId = sampleContainerId;
try
{
proxy.Delete(myContainerScope);
Console.WriteLine("Container {0} removido!", sampleContainerId);
}
catch (FaultException<Error> e)
{
if (e.Detail.StatusCode != ErrorCodes.EntityNotFound)
{
Console.WriteLine("Error: {0}:{1}", e.Detail.StatusCode, e.Detail.Message);
Console.WriteLine(e);
return;
}
Console.WriteLine("Container {0} não existente!", sampleContainerId);
}
}
}
}
A consulta aos dados publicados será tão simples quanto o uso de requisições HTTP, como:
Consultando uma Authority:
| • | https://<authority-id>.data.beta.mssds.com/v1/ |
Consultando um Container:
| • | https://<authority-id>.data.beta.mssds.com/v1/<container-id> |
Consultando uma Entity:
| • | https://<authority-id>.data.beta.mssds.com/v1/<container-id>/<entity-id> |
Podemos ainda construir consultas ao serviço para obter as entidades, containers e authorities criadas, como vemos a seguir:
Listagem 6. Exemplo de consulta para um conjunto de entitdades armazenadas no serviço SSDS.
public void QueryEntity()
{
using (SitkaSoapServiceClient proxy = new SitkaSoapServiceClient())
{
proxy.ClientCredentials.UserName.UserName = userName;
proxy.ClientCredentials.UserName.Password = password;
Scope myContainerScope = new Scope();
myContainerScope.AuthorityId = authorityId;
myContainerScope.ContainerId = containerId;
string sampleQuery = @"from e in entities
where e[""Author""] == ""Mr. Author Bob""
select e";
IEnumerable<Entity> booksByAuthor = proxy.Query(myContainerScope, sampleQuery);
}
}
Por enquanto, as url’s acima exigirão a apresentação de credenciais para o programa Beta convidado. Em breve, a Microsoft estará disponibilizando o programa Beta público e poderemos experimentar um pouco mais desse recurso em nossas arquiteturas Software + Serviço.
O ADO.NET Data Services encontra-se na mesma linha de publicação de dados na web. Ele é um dos componentes da próxima versão do ADO.NET. O projeto "Astoria", como é conhecido, permite a publicação dos dados de um banco de dados através de um serviço, permitindo a navegação dos dados através de consultas REST, suportando formatados JSON e ATOM/APP. Nesse sentido, o ADO.NET Data Services oferece a mesma funcionalidade do serviço SSDS que vimos anteriormente, porém dentro de nossa casa, no ambiente de nossa empresa.
Como principal benefício, é possível consumir as informações de um banco de dados publicado, sendo possível a busca de informações via URI, sobre o HTTP. Além disso, é possível operar sobre esses dados, uma vez que a interface utiliza todos os verbos do protocolo HTTP, como GET, POST, PUT e DELETE.
Para exemplificarmos o uso do ADO.NET Data Services e entendermos seus benefícios, vejamos um exemplo simples. Para começar, precisamos instalar alguns pacotes adicionais ao ambiente do Visual Studio 2008. A seguir, veja os principais links para download desses pacotes.
Download do ASP.NET 3.5 Extensions Preview
Download do ADO.NET Entity Framework Beta 3
Download do ADO.NET Entity Framework Tools Dec 07 Community Technology Preview
Ou apenas o pacote. NET Framework 3.5 Service Pack 1, que adiciona uma série de novos recursos e correções de forma integrada, como:
| • | .NET Framework Client Release |
| • | ASP.NET Dynamic Data |
| • | ASP.NET Routing |
| • | ADO.NET Data Services |
| • | ADO.NET Entity Framework, entre outros. |
Microsoft .NET Framework 3.5 Service pack 1 Beta
A partir dessa instalação, estaremos prontos para criar uma interface na frente de nosso banco de dados, oferecendo um serviço de publicação e navegação via internet, como veremos a seguir.
Vamos construir um exemplo de publicação de banco de dados usando o ADO.NET Data Services. A partir da instalação dos pacotes acima, vamos criar uma aplicação ASP.NET Web Application, através da escolha do template a seguir:

Figura 5 – Template para criação de uma aplicação ASP.NET Web Application.
Uma vez criada nossa aplicação, vamos adicionar um modelo de mapeamento Objeto-Relacional para nosso projeto. Esse tipo de modelo é obtido através do ADO.NET Entity Framework, que instalamos acima. O ADO.NET Entity Framework também é parte da próxima versão do ADO.NET da Microsoft, oferecendo uma série de funcionalidades e recursos para a construção de soluções multi-banco. Para saber mais sobre o ADO.NET Entity Framework, confira o blog do time de ADO.NET no link http://blogs.msdn.com/adonet/.
Desse modo, para criar um modelo EDMX, vamos adicionar um item de projeto em nossa aplicação ASP.NET, escolhendo o template indicado a seguir

Figura 6 – Template para criação de um ADO.NET Entity Data Model, ou arquivo EDMX.
Em nosso exemplo, vamos criar um modelo EDMX a partir de um banco de dados local chamado petdb.mdf. A partir desse banco, vamos mapeas as tabelas e stored procedures presentes, para nossos testes.

Figura 7 – Modelo EDMX gerado para o banco de dados petdb.mdf, que será utilizado para a publicação de dados via o ADO.NET Data Services.
A figura acima mostra um modelo EDMX criado, onde duas tabelas são mapeadas a partir do banco de dados, as tabelas people e orders.
Agora, vamos adicionar um novo item ao projeto, um ADO.NET Data Services, através do template disponibilizado pelo ASP.NET Extensions, também instalado acima.

Figura 8 – Template para adição do serviço ADO.NET Data Services
Adicionando o template do ADO.NET Data Services, o Visual Studio abre um arquivo com uma interface de serviço exemplo, que podemos usar imediatamente. Com alguns ajustes, o projeto mais simples utilizando o template ADO.NET Data Services ficaria assim:
Listagem 7. Implementação do WebDataService1.svc.cs
using System;
using System.Web;
using System.Collections.Generic;
using System.ServiceModel.Web;
using System.Linq;
using Microsoft.Data.Web;
using Model; //Modelo gerado pelo ADO.NET Entity Framework (EDMX).
namespace WebApplication1
{
public class WebDataService1 : WebDataService<Model.Entities>
{
public static void InitializeService(IWebDataServiceConfiguration config)
{
config.SetResourceContainerAccessRule("*", ResourceContainerRights.AllRead);
}
}
}
No exemplo acima, note que adicionamos o modelo EDMX através da chamada using Model, assim como indicamos o modelo de entidades que usaremos, através da declaração Model.Entities.
Rodando nossa solução, um browser será aberto e teremos a navegação pelas entidades do modelo EDMX disponível, onde as duas tabelas People e Orders são indicadas, como vemos abaixo:
Listagem 8. Retorno da chamada http://localhost:3112/WebDataService1.svc/, apresentando as tabelas Orders e People.
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <service xml:base="http://localhost:3112/WebDataService1.svc/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:app="http://www.w3.org/2007/app" xmlns="http://www.w3.org/2007/app"> <workspace> <atom:title>Default</atom:title> <collection href="Orders"> <atom:title>Orders</atom:title> </collection> <collection href="People"> <atom:title>People</atom:title> </collection> </workspace> </service>
Como vemos, a interface faz a publicação das tabelas mapeadas através do modelo EDMX, sendo possível navegar pelos dados publicados, através de consultas como:
http://localhost:3112/WebDataService1.svc/Orders
A consulta acima retorna os dados específicos da tabela Orders, através de um novo XML como apresentado na figura a seguir:
Listagem 9. Retorno da chamada http://localhost:3112/WebDataService1.svc/Orders , apresentando os dados da tabela Orders.
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<feed xml:base="http://localhost:3112/WebDataService1.svc/"
xmlns:ads="http://schemas.microsoft.com/ado/2007/08/dataweb"
xmlns:adsm="http://schemas.microsoft.com/ado/2007/08/dataweb/metadata"
xmlns="http://www.w3.org/2005/Atom">
<id>http://localhost:3112/WebDataService1.svc/Orders</id>
<updated />
<title>Orders</title>
<link rel="self" href="Orders" title="Orders" />
<entry adsm:type="Model.Orders">
<id>http://localhost:3112/WebDataService1.svc/Orders('1')</id>
<updated />
<title />
<author>
<name />
</author>
<link rel="edit" href="Orders('1')" title="Orders" />
<content type="application/xml">
<ads:OrderID>1</ads:OrderID>
<ads:Customer>Frank</ads:Customer>
<ads:Amount adsm:type="Nullable`1[System.Int32]">10</ads:Amount>
</content>
</entry>
<entry adsm:type="Model.Orders">
<id>http://localhost:3112/WebDataService1.svc/Orders('2')</id>
<updated />
<title />
<author>
<name />
</author>
<link rel="edit" href="Orders('2')" title="Orders" />
<content type="application/xml">
<ads:OrderID>2</ads:OrderID>
<ads:Customer>Bob</ads:Customer>
<ads:Amount adsm:type="Nullable`1[System.Int32]">20</ads:Amount>
</content>
</entry>
<entry adsm:type="Model.Orders">
<id>http://localhost:3112/WebDataService1.svc/Orders('3')</id>
<updated />
<title />
<author>
<name />
</author>
<link rel="edit" href="Orders('3')" title="Orders" />
<content type="application/xml">
<ads:OrderID>3</ads:OrderID>
<ads:Customer>Allan</ads:Customer>
<ads:Amount adsm:type="Nullable`1[System.Int32]">30</ads:Amount>
</content>
</entry>
</feed>
Da mesma forma, para navegar os dados da tabela People, podemos utilizar a chamada:
http://localhost:3112/WebDataService1.svc/People
A partir do exemplo acima, notamos como é simples a publicação e a navegação de um banco de dados utilizando uma interface como o ADO.NET Data Services.
O ADO.NET Data Services ainda prevê outros operadores na linha de comando HTTP, como vemos a seguir:
Tabela 1. Operadores disponíveis no ADO.NET Data Services.
Assim, são possíveis diversas consultas utilizando esses operadores, como vemos a seguir:
| • | |
| • | |
| • | |
| • | http://localhost:34425/WebDataService.svc/Orders('3')/OrderID |
| • | http://localhost:34425/WebDataService.svc/Orders?$filter=OrderID%20eq%20'1' |
Arquiteturas Software + Serviços farão uso de integrações e composições cada vez mais complexas, sendo baseadas em modelos mistos de dados locais e remotos, combinando diferentes qualidades de serviços e operações on-line e off-line.
Os projetos “Sitka” (SSDS) e “Astoria” (ADO.NET Data Services) são exemplos de infra-estruturas para esse tipo de composição. Para a criação de bancos de dados virtuais persistidos na nuvem, poderemos em breve utilizar o SSDS como parte de nossa plataforma de dados, que não precisará mais ser apenas local. Da mesma forma, poderemos oferecer interfaces web sobre nossos dados para outros sistemas da organização, utilizando interfaces REST implementadas através do ADO.NET Data Services, ampliando ainda mais a integração e o poder de composição de nossas soluções.
Este artigo foi apenas uma introdução sobre o assunto. A partir de agora, fica a sugestão para que o leitor acompanhe o desenvolvimento dessas tecnologias, experimentando e avaliando os benefícios do Software + Serviços em nossas soluções do dia-a-dia.
Algumas referências de blogs e portais interessantes sobre o assunto são listados abaixo, vale conferir:
| • | Blog da equipe “Astoria” |
| • | Blog de Pablo Castro, arquiteto responsável pelo projeto “Astoria” |
| • | Site do Projeto “Astoria” |
| • | Site do Projeto “Sitka” |
| • | Exemplos usando interface SOAP com o SQL Server Data Services |
| • | Exemplos usando interface REST com o SQL Server Data Services |
Obrigado ao Otávio Coelho, Rogério Cordeiro e Fernando Gebara pelos comentários e sugestões.
Waldemir Cambiucci trabalha na Microsoft Brasil como arquiteto de soluções, com foco na comunidade local de arquitetos e clientes corporativos. É graduado em Engenharia de Computação e mestre em Engenharia Elétrica pela Universidade de São Paulo. Com mais de 13 anos de experiência em TI, já participou de projetos importantes no Brasil e no exterior, sempre com foco em arquitetura de soluções. Possui as certificações MCP, MCSD.NET, MCAD, MCDBA, MCSA e MSF. Blog: http://blogs.msdn.com/wcamb