none
Transmitir um DataSet que tenha uma coluna com um tipo da dado não primitivo RRS feed

  • Pergunta

  • Objetivo

    Determinar um tipo de dado (DataType) customizado para um campo do DataSet.

    Esse DataSet deve transmitido via WebService

     

    Solução proposta

    Eu criei um DataSet e dentro eu criei um DataTable.

    Dentro do DataTable eu criei o campo estruturaDadoInspecao.

    O próximo passo é o tipo customizado, então eu criei o objeto EstruturaDadoInspecao.

    Como na listagem de tipo de dados (DataType) existem apenas os tipo primitivos (Int32, String, Int16 e etc) coloquei o caminho virtual do objeto EstruturaDadoInspecao no campo DataType do objeto Column.

     

    Até esse ponto eu consegui alguma coisa, o projeto compilou sem problemas, o arquivo de schema (DataSetValidacao.xsd) foi modificado pelo Visual Studio aparentemente da forma correta.

     

    O campo estruturaDadoInspecao dentro do arquivo de schema ficou da seguinte forma.

    Marcado em vermelho no final do código.

    Observem que a propriedade type="xs:anyType" está para qualquer tipo. Se fosse um campo do tipo primitivo estaria definido nessa propriedade o seu tipo. Ex: type="xs:String", type="xs:Int"

     

    <?xml version="1.0" encoding="utf-8"?>

    <xs:schema id="DataSetValidacao" targetNamespace="http://tempuri.org/DataSetValidacao.xsd" xmlns:mstns="http://tempuri.org/DataSetValidacao.xsd" xmlns="http://tempuri.org/DataSetValidacao.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:msprop="urn:schemas-microsoft-com:xml-msprop" attributeFormDefault="qualified" elementFormDefault="qualified">

      <xs:annotation>

        <xs:appinfo source="urn:schemas-microsoft-com:xml-msdatasource">

          <DataSource DefaultConnectionIndex="0" FunctionsComponentName="QueriesTableAdapter" Modifier="AutoLayout, AnsiClass, Class, Public" SchemaSerializationMode="IncludeSchema" xmlns="urn:schemas-microsoft-com:xml-msdatasource">

            <Connections>

            </Connections>

            <Tables>

            </Tables>

            <Sources>

            </Sources>

          </DataSource>

        </xs:appinfo>

      </xs:annotation>

      <xs:element name="DataSetValidacao" msdata:IsDataSet="true" msdata:UseCurrentLocale="true" msprop:Generator_UserDSName="DataSetValidacao" msprop:Generator_DataSetName="DataSetValidacao">

        <xs:complexType>

          <xs:choice minOccurs="0" maxOccurs="unbounded">

            <xs:element name="DadosValidacao" msprop:Generator_UserTableName="DadosValidacao" msprop:Generator_RowDeletedName="DadosValidacaoRowDeleted" msprop:Generator_RowChangedName="DadosValidacaoRowChanged" msprop:Generator_RowClassName="DadosValidacaoRow" msprop:Generator_RowChangingName="DadosValidacaoRowChanging" msprop:Generator_RowEvArgName="DadosValidacaoRowChangeEvent" msprop:Generator_RowEvHandlerName="DadosValidacaoRowChangeEventHandler" msprop:Generator_TableClassName="DadosValidacaoDataTable" msprop:Generator_TableVarName="tableDadosValidacao" msprop:Generator_RowDeletingName="DadosValidacaoRowDeleting" msprop:Generator_TablePropName="DadosValidacao">

              <xs:complexType>

                <xs:sequence>

                  <xs:element name="estruturaDadoInspecao" msdata:DataType="CSMB.VPS.TIA.Estruturas.EstruturaDadoInspecao, CSMB.VPS.TIA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" msprop:Generator_UserColumnName="estruturaDadoInspecao" msprop:Generator_ColumnPropNameInRow="estruturaDadoInspecao" msprop:Generator_ColumnVarNameInTable="columnestruturaDadoInspecao" msprop:Generator_ColumnPropNameInTable="estruturaDadoInspecaoColumn" type="xs:anyType" minOccurs="0" />

                </xs:sequence>

              </xs:complexType>

            </xs:element>

          </xs:choice>

        </xs:complexType>

      </xs:element>

    </xs:schema>

     

     

    Fiz um teste que mostra que provavelmente esse problema pode ser resolvido.

    Acessei o campo estruturaDadoInspecao pelo código no WebService.

     

    Problema

     

    Fiz a referência do WebSerice a cima em um projeto qualquer, apenas para teste.

    Quando executo um Build no projeto aparece o seguinte erro:

    Custom tool error: Unable to import WebService/Schema. Unable to import binding "PropostaSoap" from namespace

    "NameSpace do WebService/Nome do WebService". Unable to import operation "Nome do métdo no webservice". Column requires a valid Data Type.

     

    No WebService Studio quando eu faço um get também aparece problema.


    Conclusão

    A solução aparentemente parece ser válida porque eu consigo criar um campo em um DataSet com o tipo customizado, mas quando faço a referência do WebService não consigo acessar o campo customizado pois o objeto não foi inserido no WSDL.

     

    È preciso saber como inserir o objeto EstruturaDadoInspecao dentro do WSDL para que as aplicações que forem consumir esse WebService reconheçam esse tipo de dado (DataType).

    Caetano Marques Bruno.

    segunda-feira, 27 de setembro de 2010 12:25

Todas as Respostas

  • Caetano,

    Qual tipo de WebService você está usando? ASP.NET (*.asmx) ou WCF (*.svc)?

    Se for WCF, tente registrar o seu tipo usando o atributo KnownType, se for asp.net, tente usar o atributo XmlIncludeAttribute.

    At.,


    Rogério de Resende Ohashi | Ohashi.NET (.NET, Security, C#, WinForms, WCF, Workflow, Azure, Windows Phone, Mono)
    segunda-feira, 27 de setembro de 2010 12:37
  • Muito Obrigado pela resposta.

    O WebService é do tipo ASP.NET (*.asmx).

    Eu tentei incluir esse atributo na tag xs:element onde eu marquei de vermelho. Onde eu incluíria esse atributo?

    Caetano Marques Bruno

    segunda-feira, 27 de setembro de 2010 12:46
  • O seu DataSet é tipado?

    Se não for, você teria que criar uma classe de DataSet sua, herdada de DataSet e colocar o Atributo na classe.

    At.,


    Rogério de Resende Ohashi | Ohashi.NET (.NET, Security, C#, WinForms, WCF, Workflow, Azure, Windows Phone, Mono)
    segunda-feira, 27 de setembro de 2010 12:54
  • O meu DataSet é tipado.

    È possível fazer com ele tipado? ou ver ter que fazer como você falou, criar uma classe de DataSet.

    Caetano Marques Bruno.

    segunda-feira, 27 de setembro de 2010 13:01
  • Sim, é só colocar o atributo na sua classe tipada.

    Clique com o botão direito sobre o seu DataSet e selecione View Code e coloque o atributo informando o seu tipo personalizado:

    [XmlInclude(typeof(SeuTipo))]
    public partial class MyDataset
    {
    
    }
    

    At.,


    Rogério de Resende Ohashi | Ohashi.NET (.NET, Security, C#, WinForms, WCF, Workflow, Azure, Windows Phone, Mono)
    segunda-feira, 27 de setembro de 2010 13:05
  • Rogério, fiz a alteração como você falou.

    [XmlInclude(typeof(EstruturaDadoInspecao))]
      public partial class DataSetValidacao {
        [XmlInclude(typeof(EstruturaDadoInspecao))]
        partial class DadosValidacaoDataTable
        {
          
        }
      }
    

    Mas na aplicação que está consumindo este WebService ainda está dando erro.

    Failed to load dataset because of the following erro: column requires a valid DataType.

    Dentro do DataSet eu coloquei no tipo do campo o caminho da aplicaçao para ele encontrar o tipo que eu criei: NomeProjeto.Estruturas.EstruturaDadoInspecao

    Caetano Marques Bruno.

    segunda-feira, 27 de setembro de 2010 13:39
  • Rogério eu encontrei uma funcionalidade aqui no VS que nunca tinha visto.

    Eu cliquei com o botão direito do mouse em cima do meu DataSet e selecionei a opção Open with e selecionei XML Schema Editor.

    Talvez isso possa ajudar em alguma coisa.

     

    Caetano Marques Bruno.

    segunda-feira, 27 de setembro de 2010 14:34
  • Cara,

    Acho que isto não vai resolver o seu problema.

    Eu vou dar uma estudada hoje sobre este assunto porque vou fazer a certificação sobre este assunto depois de amanhã, qualquer coisa eu te dou mais umas dicas.

    at.,


    Rogério de Resende Ohashi | Ohashi.NET (.NET, Security, C#, WinForms, WCF, Workflow, Azure, Windows Phone, Mono)
    terça-feira, 28 de setembro de 2010 19:33
  • OK, eu aguardo.

    Boa sorte

    Obrigado.

     

    Caetano

    quarta-feira, 29 de setembro de 2010 14:33
  • Rapaz, acho que você vai ter um bocado de dor de cabeça para concluir isso aí. O problema está na serialização do DataSet. No seu WebService, acrescenta uma linha de código para salvar o seu dataset em um arquivo xml antes de retornar ele... Algo tipo:

    dataSetTipado.WriteXml(@"c:\teste.xml");

     

    Depois, dá uma olhadinha. A serialização padrão desse tipo que você criou vai fazer com que o xml contenha atributos de namespace na seção de dados. Na hora de desserializar, a classe do DataSet vai chiar...

    Para expor qualquer classe, basta que no seu WebService você declare um método público que receba ou retorne algo do tipo que você quer expor. Mas isso não vai adiantar.

    Meu conselho é o de que você retorne uma Lista de itens que contenham a estrutura de dados que você quer retornar para  seu cliente. Vai dar menos trabalho, e pelo que eu entendi, você só precisa ler esses dados, ou seja. Nunca vai mandar o dataset de volta para o server com suas alterações.

     

    Boa Sorte


    ...
    quinta-feira, 21 de outubro de 2010 01:20