Arquivos XML: Web Services e DataSets

Propaganda
Os Arquivos XML:
Web Services e DataSets
Texto Original: MSDN Magazine / Aaron Skonnard
Traduzido por: Luis Gustavo Amaro (http://www.spigandoeaprendendo.wordpress.com)
*Atenção a possíveis erros de tradução! =D
Web Services e DataSets
Programadores que utilizam Visual Basic 6.0 se curvaram ao altar dos conjuntos de registros ADO. Que é provavelmente a
estrutura de dados mais utilizada em aplicativos baseados em Windows hoje em dia. A ADO.NET Datasets está pronta para
desempenhar um papel similar no campo de gestão de aplicativos baseados em Windows.
Quando você precisa extrair informação da base de dados, apresentar isso ao usuário, e aplicar atualizações, o DataSet é
normalmente o melhor caminho. O DataSet foi utilizado com bastante sucesso para uma variedade de soluções tendo como alvo o
Microsoft .Net Framework. No caso de Web Services, o DataSet pode causar problemas de interoperabilidade.
Se você utiliza estruturas de dados dinâmica como o DataSet isso pode ser difícil para desenvolvedores que usam outras
ferramentas para consumir seu Web Service. Usando DataSets tipados em combinação com definições WSDL levemente
customizados, contudo, fica entorno desta questão. Desenvolvedores precisam entender as questões que envolvem todas as
estruturas de dados dinâmicos (como o DataSet) antes de utiliza-los nas interfaces Web Services.
Níveis de Interoperabilidade
A habilidade para processar o dado indiferente de onde ele vem é o maior nível primitivo da interoperabilidade. Eu gosto de
chamar isto de “interoperabilidade de dados.” XML 1.0 foi desenvolvido especificamente para facilitar a interoperabilidade dos
dados.
O dado serializado dentro do XML 1.0 é fácil para extrair e manipular em qualquer plataforma utilizando qualquer linguagem de
programação para cada processador de XML existente, que engloba praticamente todas as linguagens hoje em dia. Alcançar a
interoperabilidade de dados ainda requer que você escreva o código junto a uma API XML exposta pelo seu processador de XML,
mas você não precisa lidar com o byte stream diretamente (veja a Figura 1).
Figura 1 Interoperabilidade de dados através do XML
Aplicando XML à tecnologia de aplicação distribuída (Web Services) simplifica a interoperabilidade entre sistemas heterogêneos
distribuídos. Web Services podem ser construídos diretamente utilizando APIs XML. Esta aproximação lhe dá total controle sobre
o processamento de mensagem, mas exige que você implemente um contrato comum na infra-estrutura do Web Service, que possa
diminuir a produtividade e introduzir erros que podem levar a mais problemas de interoperabilidade.
Vendedores de tecnologias distribuídas (como Microsoft) passaram ocupadas desenvolvendo ferramentas Web Services que
proporcionam essa infra-estrutura comum, ajudando reduzir o código da API XML necessária do desenvolvedor Web Service. O
Microsoft ASP.NET WebMethod framework é uma das ferramentas que remove quase todos os traços do baixo nível System.Xml
APIs. Ferramentas Web Services realizam isto pela definição mapeamentos entre tipos de aplicativos e tipos de XML Schema,
assim automatizando as transações entre os documentos XML e os objetos de instância em tempo de execução.
Por exemplo, considerando o seguinte WebMethod chamado CalculateMortgage que recebe um objeto MortgageInfo como
parâmetro e retorna um objeto MortgagePayments:
[WebService(Namespace="http://example.org/mortgage")]
public class MortgageService : WebService {
[WebMethod]
public MortgagePayments CalculateMortgage(MortgageInfo minfo){
... // calculate mortgage
return new MortgagePayments();
}
}
Dentro deste mótodo, o desenvolvedor está simplesmente trabalhando com objetos, mas o [WebMethod] atributo diz a infraestrutura ASP.NET para tratar este método como operação Web Service. Então neste caso a infra-estrutura automaticamente
mapeia as classes MortgageInfo e MortagePayment para definições do tipo XML Schema.
Figura 2 mostra a definição das classes MortgageInfo e MortagePayment em C#, utilizadas pelo CalculateMortgage WebMethod,
enquanto na Figura 3 mostra as definições do tipo XML Schema geradas pela infra-estrutura ASP.NET. Com estas definições
XML Schema no lugar, está claro o que o outro lado deve esperar em termos de XML.
Figure 3 Definições do tipo XML Schema:
•••
<s:complexType name="MortgageInfo">
<s:sequence>
<s:element name="amount" type="s:double" />
<s:element name="years" type="s:double" />
<s:element name="interest" type="s:double" />
<s:element name="annualTax" type="s:double" />
<s:element name="annualInsurance" type="s:double" />
</s:sequence>
</s:complexType>
<s:complexType name="MortgagePayments">
<s:sequence>
<s:element name="MonthlyPI" type="s:double" />
<s:element name="MonthlyTax" type="s:double" />
<s:element name="MonthlyInsurance" type="s:double" />
<s:element name="MonthlyTotal" type="s:double" />
</s:sequence>
</s:complexType>
•••
Figure 2 Definições de classe:
public class MortgageInfo
{
public double amount;
public double years;
public double interest;
public double annualTax;
public double annualInsurance;
}
public class MortgagePayments
{
public double MonthlyPI;
public double MonthlyTax;
public double MonthlyInsurance;
public double MonthlyTotal;
}
Ferramentas Web Service fazem isso fácil para ignorar o XML já que o desenvolvedor Web Service lidará apenas com objetos.
A Ferramenta do outro lado, porém, também quer mapear o XML para objetos. Por exemplo, um desenvolvedor que usa
linguagem Java pode usar algo como a ferramenta Apache Axis para consumir este Web Service. Para usar então, ele poderia usar
o utilitário WSDL2java para gerar automaticamente classes Java pelas definições do tipo XML Schema (veja Figura 4). Torna
possível também ao desenvolvedor Java trabalhar com o objeto sem precisar descer para o baixo-nível do XML APIs Java.
Figure 4 Definições de classe Java gerada pelo Apache Axis:
/**
* MortgageInfo.java
*
* This file was auto-generated from WSDL
* by the Apache Axis WSDL2Java emitter.
*/
public class MortgageInfo implements java.io.Serializable {
private double amount;
private double years;
private double interest;
private double annualTax;
private double annualInsurance;
public MortgageInfo() {
}
public double getAmount() {
return amount;
}
public void setAmount(double amount) {
this.amount = amount;
}
... // remainder ommited for brevity
}
/**
* MortgagePayments.java
*
* This file was auto-generated from WSDL
* by the Apache Axis WSDL2Java emitter.
*/
package mortgage_tools;
public class MortgagePayments implements java.io.Serializable {
private double monthlyPI;
private double monthlyTax;
private double monthlyInsurance;
private double monthlyTotal;
public MortgagePayments() {
}
public double getMonthlyPI() {
return monthlyPI;
}
public void setMonthlyPI(double monthlyPI) {
this.monthlyPI = monthlyPI;
}
... // remainder omitted for brevity
}
Agora vamos discutir o próximo nível da interoperabilidade – que eu gosto de chamar de “Interoperabilidade de ferramenta”.
Interoperabilidade de ferramenta significa que eu posso escrever um código Web Service em um ferramenta e facilmente
consumi-la usando outra ferramenta sem descer para o baixo-nível das APIs XML. Deve ter um objeto equivalente mapeado ou o
outro lado deverá descer o nível e tratar diretamente com o XML (isto está ilustrado na Figura 5).
Figura 5 Interoperabilidade de ferramenta
Interoperabilidade de ferramenta é difícil devido a muitas diferenças nas linguagens de programação e tipos de sistemas. O
DataSet é um tipo quer apresenta alguns desafios interessantes para interoperabilidade de ferramenta.
Problema do DataSet
A maioria das ferramentas Web Services fazem um bom trabalho mapeando definições de classes simples como mostramos
anteriormente. Eles começam a encontrar problemas, no entanto, quando derivação e substituição entram em jogo, ou quando
tipos dinâmicos são utilizados, assim como collections, hash tables, or DataSets. Você deve considerar a seguinte assinatura do
framework .NET:
[WebMethod]
public DataSet GetAuthors()
{
... // return DataSet filled with authors
}
Oque deve ser mapeado do DataSet em termos de XML Schema? O DataSet é um tipo polimórfico do qual o layout atual não foi
determinado ainda em tempo de execução, depois que o DataSet foi preenchido com dados.
A seguinte definição do XML Schema contém a declaração do elemento para GetAuthorsResponse. Note que
GetAuthorsResponse contém um elemento opcional chamado GetAuthorsResult, que contém 2 filhos: um elemento esquema
XMLSchema (s:schema), seguido por um coringa (wildcard) (s:any) indicando que qualquer elemento de qualquer namespace
pode ser fornecido.
<s:element name="GetAuthorsResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="GetAuthorsResult">
<s:complexType>
<s:sequence>
<s:element ref="s:schema" />
<s:any />
•••
</s:element>
Isso indica que um esquema será fornecido em tempo de execução que será descrito o XML que conterá o mesmo. Aqui está
como isso deveria parecer na resposta SOAP:
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:s="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetAuthorsResponse
xmlns="http://example.org/dataset-service">
<GetAuthorsResult>
<s:schema> *** schema goes here *** </s:schema>
*** xml goes here ***
•••
</soap:Envelope>
Desde que a ferramenta não esteja apta para determinar o tipo atual usado no DataSet até o tempo de execução, a próxima questão
é que a definição do XML Schema (apenas mostrado) deve ser mapeado no outro ambiente como a ferramenta Apache’s Axis.
Ligação de Ferramentas
No momento de estruturação, quando o desenvolvedor Java roda WSDL2Java, não terá informações suficientes na definição do
esquema para fazer qualquer outra coisa a não ser mapear o elemento s:any para java.lang.Object, como:
•••
public class GetAuthorsResult implements java.io.Serializable {
private java.lang.Object any;
... // omitted for brevity
}
Como podemos ver, o Axis não consegue ir muito longe, porque não é como a referencia para o elemento s:schema que precede o
s:any; isso gera uma exceção e falhas para produzir qualquer coisa deste tipo. Se o esquema referenciado não existir, sendo assim,
a classe Java seria algo parecido com o mostrado anteriormente.
Desde que nem o desenvolvedor nem a ferramenta tenha qualquer tipo adicional de informação (sobre a estrutura da informação
do autor neste caso), a unica coisa que faz sentido é para a ferramenta fornecer uma DOM tree (estrutura Document Object
Model) no campo que contém o XML interpretado. Por isso, para que desenvolvedores Java consumam este Web Service, eles
precisarão descer e utilizar a sua API DOM equivalente diretamente. O código na Figura 6 mostra como fazer isto.
Figura 6 Programa Cliente Axis (Usando APIs XML)
import java.io.*;
import org.example.*;
import org.w3c.dom.*;
import org.apache.xerces.dom.*;
import org.apache.axis.message.*;
public class AuthorsClient {
static void main(String[] args) throws Exception {
DataSetServiceSoapStub stub =
new DataSetServiceSoapStub(new java.net.URL("http://localhost/ds/ds.asmx"), null);
GetAuthorsAsTypedDataSetResult result =
Object any = result.getAny();
// it's really a DOM tree
Element docElement = (Element)any;
stub.getAuthors();
NodeList authors = docElement.getElementsByTagNameNS("http://example.org/dataset", "authors");
for (int i=0; i<authors.getLength(); i++)
{
Element authorsElem = (Element)authors.item(i);
ElementImpl fnameElem = (ElementImpl)authorsElem.getElementsByTagNameNS(
"http://example.org/dataset","au_fname").item(0);
System.out.println(fnameElem.getTextContent());
}
}
}
Nós vamos nos deparar com este problema com qualquer ferramenta, isso não é um caso especial para os DataSets no .NET
Framework. Você sempre precisara negociar com a DOM API diretamente usando a ferramenta Microsoft SOAP para
desenvolvedores COM.
De acordo com as definições que eu disponibilizei anteriormente, ainda há interoperabilidade de dados nesta situação (isto é
apenas XML), mas um nível da interoperabilidade de ferramenta é perdida desde que o desenvolvedor é obrigado a negociar com
o XML puro. Se eu sei que estou retornando uma coleção de gravações do autor com um formato bem definido, existem algumas
maneiras que eu poderia fazer isto facilmente para usuários de outras ferramentas, para processar meus dados sem acessar as
APIs XML diretamente.
Evitando DataSets
Provavelmente o jeito mais fácil de fazer isso, é não utilizar DataSets na sua interface Web Service. Por exemplo, neste caso você
poderia definir uma classe que modela as informações do autor, e declarar o método GetAuthors como a seguir:
public class Author
{
public string id;
public string au_fname;
public string au_lname;
•••
}
[WebMethod]
public Author[] GetAuthors()
{
DataSet authorsDS = GetAuthorsFromDB();
... // walk through DataSet and generate
// Author array to return
}
Aqui estou mapeando manualmente um DataSet para um tipo estático do Author (já que estou provavelmente usando o DataSet
aqui para receber os dados do banco de dados, provavelmente faz mais sentido usar IDataReader diretamente, podendo prover
uma solução mais eficiente). Neste caso eu poderia fazer naturalmente um mapeamento entre a classe Author e a definição do
XML Schema equivalente, que mapearia também de volta muito bem para uma classe Java equivalente (como o exemplo
CalculateMortgage mostrado anteriormente).
Com algo assim no lugar, o desenvolvedor Axis poderia estar apto a escrever um código sem precisar acessar as API’s XML
diretamente (veja a Figura 7). Outra maneira de efetuar isto poderia ser gerar um DataSet tipado de uma definição XML Schema
e usá-la no lugar de um DataSet genérico.
Figura 7 Cliente Axis (Sem APIs XML)
import java.io.*;
import org.example.*;
public class AuthorsClient {
static void main(String[] args) throws Exception
{
DataSetServiceSoapStub stub = new DataSetServiceSoapStub(new java.net.URL(
"http://localhost/ds/ds.asmx"), null);
Author[] authors = stub.getAuthors();
for (int i=0; i<authors.length; i++)
System.out.println(authors[i].getAu_Fname());
}
}
DataSets Tipados
DataSets Tipados são classes derivadas de DataSets e expõe os membros fortemente tipados que descrevem uma visão específica
dos dados. Diferente dos DataSets genéricos, os DataSets tipados são obrigado a uma estrutura específica, uma definição de XML
Schema, em tempo de projeto. Você pode gerar automaticamente DataSets tipados a partir de definições XML Schema usando o
xsd.exe ou os designers embutidos no Visual Studio .NET.
Figura 8 contém uma definição XML Schema que descreve as gravações do autor que eu pretendo retornar para minha Web
Service. Após executar este esquema através do xsd.exe usando o /dataset switch (ou o designer do Visual Studio .NET), Eu terei
uma nova classe chamada AuthorSet derivada do DataSet, como mostrado aqui:
[Serializable()]
public class AuthorSet : DataSet {
private authorsDataTable tableauthors;
... // strongly typed accessors
}
Figura 8 Definição do XML Schema do DataSet Tipado (AuthorSet.xsd)
<xs:schema id="AuthorSet"
targetNamespace="http://example.org/dataset"
xmlns="http://example.org/dataset"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
...
>
<xs:element name="AuthorSet" ...>
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="authors">
<xs:complexType>
<xs:sequence>
<xs:element name="au_id" type="xs:string" />
<xs:element name="au_lname" type="xs:string" />
<xs:element name="au_fname" type="xs:string" />
...
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
...
</xs:element>
</xs:schema>
A infra-estrutura sabe que a definição do esquema deve ser para este DataSet tipado, então ele não precisa mais prover um
esquema em tempo de execução (embora ele ainda faz). Agora nós podemos criar um novo WebMethod que retorna um objeto
AuthorSet:
[WebMethod]
public AuthorSet GetAuthorsAsTypedDataSet()
{
AuthorSet aus = new AuthorSet();
sqlDataAdapter1.Fill(aus);
return aus;
}
Agora a infra-estrutura tem informação suficiente para informar os clientes em tempo de projeto sobre a estrutura das gravações
do autor no conjunto retornado. Quando a estrutura ASP.NET gerar o WSDL e as definições do XML Schema, contudo, importa
as definições XML Schema do DataSet tipado e utiliza coringa restrito, como mostrado na Figura 9.
Figura 9 Definição XML Schema do método GetAuthorsAsTypedDataSet
<definitions
xmlns:s="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.org/dataset-service"
xmlns="http://schemas.xmlsoap.org/wsdl/"
...
>
<import namespace="http://example.org/dataset" location="http://localhost/ds/ds.asmx?schema=AuthorSet" />
<types>
<s:schema elementFormDefault="qualified" targetNamespace="http://example.org/dataset-service">
<s:import namespace="http://example.org/dataset" />
...
<s:element name="GetAuthorsAsTypedDataSetResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="GetAuthorsAsTypedDataSetResult">
<s:complexType>
<s:sequence>
<s:any
namespace="http://example.org/dataset" />
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
...
</s:schema>
...
</definitions>
Uma vez que já não há referência para o elemento s:schema, WSDL2Java está apto a gerar as classes Java corretamente. E uma
vez que importado as definições lhe dá acesso as definições do XML Schema para AuthorSet, isto pode gerar as classes Java
equivalentes que representam as informações do autor. Axis, contudo, ainda mapeia o coringa (s:any) para java.lang.Object, quais
vão conter uma DOM tree (estrutura Document Object Model) em tempo de execução. Isso me deixa ainda mais do que antes,
mas ainda deixa o cliente trabalhando com a API DOM diretamente.
Customizando o Esquema
Uma vez que você sabe que o slot coringa sempre conterá um AuthorSet, você pode ser tentado apenas a modificar a definição do
esquema para referenciar o elemento AuthorSet ao invés do coringa. O coringa, contudo, é atualmente um espaço reservado para o
esquema do DataSet genérico (que não faz muito sentido uma vez que o coringa está amarrado ao http://example.org/dataset
namespace). Em outras palavras, quando você executa o WebMethod, o elemento GetAuthorsAsTypeDataSetResult conterá um
elemento esquema seguido por um elemento diffgram, e o elemento diffgram conterá o elemento AuthorSet.
Mas uma vez que você conhece a estrutura antes da hora, você não precisa fornecer um esquema em tempo de execução ou um
elemento diffgram; você pode simplesmente retornar um elemento AuthorSet. O modo de fazer isto é definir um novo
WebMethod que não retorna um DataSet, mas sim um XmlNode. Então se você retornar um XmlDataDocument que envolve um
objeto DataSet tipado, apenas o elemento AuthorSet é retornado ao cliente, sem o esquema de tempo de execução ou elementos
diffgram:
[WebMethod]
public XmlNode GetAuthorsAsXml()
{
AuthorSet aus = new AuthorSet();
sqlDataAdapter1.Fill(aus);
return new XmlDataDocument(aus);
}
O XmlDataDocument é ineficiente uma vez que ele praticamente dobra o tamanho do DataSet original. Desde que seja por pouco
tempo, isso pode ser aceitável.
Especificando que o método retorna um XmlNode também irá resultar em um coringa no esquema gerado, mas agora você pode
reescrever o coringa com uma referência ao elemento AuthorSet, como mostrado a seguir:
•••
<s:element name="GetAuthorsAsXmlResponse">
<s:complexType>
<s:sequence>
<s:element minOccurs="0" maxOccurs="1"
name="GetAuthorsAsXmlResult">
<s:complexType>
<s:sequence>
<s:element ref="x:AuthorSet" />
</s:sequence>
</s:complexType>
•••
Você deverá ter certeza que os clientes não recuperarão o arquivo WSDL gerado automaticamente uma vez que você iniciar este
caminho. Em vez de você vai querer especificar a localização de um arquivo WSDL customizado usando o
WebServiceBindingAttribute (veja a prorpriedade Location) ou fornecendo um arquivo WSDL estático no seu servidor e
desabilitando a geração automática do WSDL. Você pode desabilitar a geração automática do WSDL adicionando a seguinte
sessão no seu arquivo web.config:
<webServices>
<protocols>
<remove name="Documentation" />
</protocols>
</webServices>
Agora o WebService pode ainda trabalhar com DataSets e outros clientes podem processar os resultados como um array de
objetos. Figura 10 mostra como um cliente Axis se parece neste caso.
Figura 10 Cliente Axis de um DataSet Tipado
import org.example.*;
public class AuthorsClient {
static void main(String[] args) throws Exception {
DataSetServiceSoapStub stub = new DataSetServiceSoapStub(new java.net.URL (
"http://localhost/ds/ds.asmx"), null);
GetAuthorsAsTypedDataSetResult res = stub.getAuthorsAsTypedDataSet();
AuthorSet aset = res.getAuthorSet();
Author[] authors = aset.getAuthors();
for (int i=0; i<authors.length; i++)
System.out.println(authors[i].getAu_Fname());
}
}
Se isso parecer uma grande confusão usar DataSets, você pode sempre evitar eles nas suas interfaces Web Services ou
simplesmente exigir de seus cliente que lidem diretamente com o XML. Isso tudo se resume ao o que você quer que as outras
ferramentas vejam.
A Solução Final
Este problema poderia eventualmente sumir se a indústria definisse um padrão de definição do XML Schema para representar os
conjuntos de resultados do banco de dados e todas as ferramentas suportem isso apropriadamente. Então as ferramentas poderiam
mapear seus tipos de conjuntos de dados nativos para o esquema padronizado. A mesma coisa para outros tipos dinâmicos como
collections, hash tables, lists, queues, e muito mais. Padronizando as definições do XML Schema para tais tipos teria o efeito de
promover a interoperabilidade de ferramenta através de uma vasta gama de extrema eficiência e geralmente estruturas de dados
usadas.
Se isso fosse uma realidade, você poderia retornar uma DataSet genérico (como o primeiro exemplo GetAuthors) e a ferramenta
Axis poderia mapeá-la para um JDBC WebRowSet (ou algo equivalente). Então o desenvolvedor Java poderia ligar o
WebRowSet com um componente UI, permite o usuário modificar o dado, e passar um conjunto atualizado de volta ao servidor –
tudo com muito pouco código. O conjunto atualizado pode então ser deserializado de volta dentro do DataSet no servidor, a fim
de aplicar as alterações aos dados.
Esta solução faz o maior sentido, se você pensa porque você precisa utilizar um DataSet em um Web Service. DataSets são
tipicalmente usado quando você precisa apresentar um dado ao usuario de uma forma genérica (normalmente em uma grade),
permitindo o usuário fazer modificações, e devolver as atualizações ao servidor. As técnicas apresentadas aqui não suportam este
padrão (desde que você não receba vinculação de dado ou suporte diffgram com DOM tree (estrutura Document Object Model) ou
arrays), então isto é como martelar um taco quadrado em um buraco redondo.
Claro, padronizar qualquer coisa nesta indústria é muito mais fácil dizer do que fazer. Não prenda a respiração esperando por cada
padrões que venham codificados e suportados inteiramente nas ferramentas de hoje em dia.
Uma Solução .Net Framework
Você provavelmente já viu demonstrações em feiras de negócio no passado aonde o apresentador retornava um DataSet para um
cliente .Net Framework e de alguma maneira isto magicamente tornava-se um DataSet do outro lado. Isto funciona porque a infraestrutura Web Service no .Net Framework procura por uma flag especial na definição do XML Schema fornecido em tempo de
execução chamado IsDataSet. Por exemplo, no caso do exemplo GetAuthorsAsTypedDataSet, declaração do elemento AuthorSet
parecerá como isto no esquema fornecido em tempo de execução:
•••
<xs:element name="AuthorSet" msdata:IsDataSet="true">
•••
A flag IsDataSet é o “toque” para o cliente, dizendo para deserializar o XML dentro de um DataSet. Obviamente, isto funciona
apenas para cliente .Net Framework ou outras ferramentas que tem fornecido este caso especial codificado (não tem nenhum que
eu conheça atualmente). O código na Figura 11 mostra como um cliente Visual Basic .NET poderia invocar ambos GetAuthors e
GetAuthorsAsTypedDataSet e facilmente mapear o DataSet retornado para um DataGrid (em um formulário Windows).
Figura 11 Mapeando um DataSet para um DataGrid
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim svc As DataSetService = New DataSetService()
Dim ds As DataSet = svc.GetAuthors()
DataGrid1.DataSource = ds.Tables.Item(0)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Dim svc As DataSetService = New DataSetService()
Dim auset As AuthorSet = svc.GetAuthorsAsTypedDataSet()
DataGrid1.DataSource = auset.authors
End Sub
Isto deveria ser apenas como uma fácil através de todas as ferramentas e uma variedade APIs de banco de dados se tivéssemos
uma esquema padronizado para os conjuntos de resultados de banco de dados que todos suportassem. Ironicamente, uma vez que
você tem algo assim no lugar, atualmente isto é mais tedioso trabalhar com um array de objetos Author quando o sua meta é
apresentar o dado ao usuário para uma manipulação genérica.
Resumindo
XML e Web Services fornecem interoperabilidade básica de dados atualmente. Se você estiver disposto a trabalhar com APIs
XML, não há um Web Service no mundo que você não consiga consumir. Se, contudo, se você prefere esconder as APIs XML
embaixo do tapete e nunca lidar com ele de novo, tenha cuidado com tipo dinâmicos como o DataSet. Utilizazndo o DataSet
genérico na interface DataSet forçará os desenvolvedores a usar outras ferramentas para lidar com o XML diretamente. Utilizando
DataSets tipados em combinação com definições WSDL levemente customizadas contorna este problema expondo os resultados
como um simples array de objetos. A solução definitiva, contudo, seria padronizar uma definição de XML Schema para
representar conjuntos de resultados de banco de dados que poderia ser comportado em todos as ferramentas.
Envie suas dúvidas e comentários (em inglês) para Aaron > [email protected].
Download