ActiveDelphi - Índice do Fórum ActiveDelphi
.: O site do programador Delphi! :.
 
 FAQFAQ   PesquisarPesquisar   MembrosMembros   GruposGrupos   RegistrarRegistrar 
 PerfilPerfil   Entrar e ver Mensagens ParticularesEntrar e ver Mensagens Particulares   EntrarEntrar 

DBXReader de um TClientDataSet? [RESOLVIDO]
Ir à página 1, 2  Próximo
 
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Delphi
Exibir mensagem anterior :: Exibir próxima mensagem  
Autor Mensagem
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Jan 13, 2012 11:33 am    Assunto: DBXReader de um TClientDataSet? [RESOLVIDO] Responder com Citação

Bom dia pessoal!

Existe algum macete na utilização do TDBXDataSetReader.Create( TDataSet, False )?

Estou criando um TClientDataSet temporario, com o método CreateDataSet, e preenchendo seu conteúdo de forma padrão. Até então, tudo ok!

Porém, gostaria que meu ServerMethod retornasse um TDBXReader desse dataset criado. Nesse momento, executo o comando acima mas o retorno é sempre nil, como se ele não criasse nada!

Imaginando que meu dataset criado se chama CDSEmpresas e que o mesmo possui 4 registros, o código da função é o abaixo:
Código:
result := TDBXDataSetReader.Create( CDSEmpresas, True );


Editado pela última vez por JCMF em Seg Jan 16, 2012 9:31 am, num total de 1 vez
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Jan 13, 2012 2:00 pm    Assunto: Responder com Citação

E então pessoas? Ninguém já chegou a utilizar um DBXReader ou o TDBXDataSetReader?
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Jan 13, 2012 2:45 pm    Assunto: Responder com Citação

Encontrei esse exemplo no blog do Andreano mas, oq aparentemente é extremamente simples, não está funcionando comigo =\

http://www.andreanolanusse.com/en/copying-data-from-clientdataset-to-dbxreader/

Código:

TDBXDataSetReader.Create(ClientDataSet, False (* InstanceOwner *) )


Ninguém se habilita? =)
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Jan 13, 2012 3:23 pm    Assunto: Responder com Citação

Decidi postar o código completo para dar uma ajuda... algumas classes e métodos são específicos de nosso sistema daqui então, não se preocupem com oq eles fazem... Mas, se for preciso, só perguntar! Wink

O código tá grande mas super simples de entender!

Este é o código na minha aplicação servidor:
Código:
function TServerModuleEmpresa.GetUserCompanies(idUsuario: Integer; isMaster, isAdmin: Boolean): TDBXReader;

  { ** Procedimento interno do método para definir o ClientDataSet temporário para retorno ** }
  function CreateCDSEmpresas: TClientDataSet;
  var
    cdsFieldPos: Integer;
    cdsTable: TNewTable;
  begin

    { ** Criando o objeto de retorno ** }
    result := TClientDataSet.Create( Self );

    { ** Recuperando o objeto NewTable de empresas ** }
    cdsTable := Structure.GetTable( 'empresas' );

    { ** Varrendo a estrutura da empresa para a definição dos campos do dataset de retorno ** }
    for cdsFieldPos := 0 to High( cdsTable.Fields ) do
      with cdsTable.Fields[cdsFieldPos] do
        begin

          case FieldType of

            nftInteger, nftAutoIncrement:
              result.FieldDefs.Add( Name, ftInteger, FieldSize );

            nftVarchar, nftChar:
              result.FieldDefs.Add( Name, ftString, FieldSize );

            nftBlob:
              result.FieldDefs.Add( Name, ftBlob, FieldSize );

            nftDecimal:
              result.FieldDefs.Add( Name, ftCurrency, FieldSize );

            nftFloat:
              result.FieldDefs.Add( Name, ftFloat, FieldSize );

            nftDate:
              result.FieldDefs.Add( Name, ftDate, FieldSize );

            nftTime:
              result.FieldDefs.Add( Name, ftTime, FieldSize );

            nftDateTime:
              result.FieldDefs.Add( Name, ftDateTime, FieldSize );

            nftTimestamp:
              result.FieldDefs.Add( Name, ftTimeStamp, FieldSize );

            nftText:
              result.FieldDefs.Add( Name, ftMemo, FieldSize );

          end;

        end;

    { ** Gerando o Dataset do objeto de retorno ** }
    result.CreateDataSet;

  end;

var
  builder: TQueryBuilderAbstract;
  builderIn: TQueryBuilderAbstract;
  CDSEmpresas: TClientDataSet;
  pos: Integer;
begin

  { ** Criando o dataset de retorno ** }
  CDSEmpresas := CreateCDSEmpresas;

  { ** Definindo a consulta padrão para a seleção das empresas permitidas pelo usuário logado ** }
  builder := GetPreparedBuilder;

  try

    { ** Montando a instrução para filtrar as empresas permitidas para o usuário logado, quando não for MASTER ** }
    if not isMaster and not isAdmin then
      begin

        { ** Usuário não é Administrador do sistema ** }
        builderIn := CreateQueryBuilder( 'empresas_usuarios', 'empresas_usuarios' );

        builderIn.AddField( 'id_empresa' );
        builderIn.AddWhere( 'id_usuario = ' + IntToStr( idUsuario ) );
        builderIn.AddOrderBy( 'razao_social' );

        builder.AddWhere( 'bloqueado = ' + QuotedStr( 'F' ) );
        builder.AddWhere( 'and id in( ' + builderIn.GetInstruction + ' )' );

        { ** Liberando o objeto builderIn da memória ** }
        builderIn.Destroy;

      end;

    { ** Recuperando as empresas permitidas pelo usuário logado ** }
    builder.Open;

    { ** Populando o objeto de retorno ** }
    while not builder.Dataset.Eof do
      begin

        CDSEmpresas.Append;

        { ** Adicionando os campos para o registro ** }
        for pos := 0 to builder.Dataset.FieldCount - 1 do
          if CDSEmpresas.FindField( builder.Dataset.Fields[pos].FieldName ) <> nil then
            CDSEmpresas.FieldByName( builder.Dataset.Fields[pos].FieldName ).Value := builder.Dataset.Fields[pos].Value;

        { ** Gravando a informação do registro no dataset de retorno ** }
        CDSEmpresas.Post;

        { ** Avançando para o próximo registro disponível ** }
        builder.Dataset.Next;

      end;

    { ** Definindo o retorno do método ** }
    result := TDBXDataSetReader.Create( CDSEmpresas, False );

    { ** Finalizando o objeto de retorno criado ** }
    CDSEmpresas.Free;

    { ** Finalizando o objeto builder criado ** }
    builder.Destroy( True );

  except
    raise Exception.Create( cstMsgSistemaFalhaEmpresasUsuarioLogado );
  end;

end;


Esta é a chamada na minha aplicação cliente:
Código:
function TFormSelecaoEmpresa.SelectionCompanies: Boolean;
var
  DBXCommand: TDBXCommand;
  DBXLeitor: TDBXReader;
begin

  result := False;

  { ** Definindo o comando para a execução do Server Method ** }
  DBXCommand := DataSnapConnection.DBXConnection.CreateCommand;
  DBXCommand.CommandType := TDBXCommandTypes.DSServerMethod;

  try

    { ** Recuperando as empresas disponíveis para o usuário logado no sistema ** }
    DBXCommand.Text := 'TServerModuleEmpresa.GetUserCompanies';
    DBXCommand.Prepare;
    DBXCommand.Parameters[0].Value.SetInt32( usuario.Id );
    DBXCommand.Parameters[1].Value.SetBoolean( usuario.Master );
    DBXCommand.Parameters[2].Value.SetBoolean( usuario.Administrador );

    try

      DBXCommand.ExecuteUpdate;

      { ** Recuperando o retorno do comando realizado ** }
      DBXLeitor := DBXCommand.Parameters[3].Value.GetDBXReader( True );

      TDBXDataSetReader.CopyReaderToClientDataSet( DBXLeitor, cdsSelecao );

      cdsSelecao.Active := True;

    except on Error: Exception do
      TCommonUtilities.MsgWarning( Error.Message );
    end;

  finally
    FreeAndNil( DBXCommand );
  end;

end;
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
andreano
Novato
Novato


Registrado: Terça-Feira, 7 de Junho de 2005
Mensagens: 86

MensagemEnviada: Sex Jan 13, 2012 3:32 pm    Assunto: Responder com Citação

Remove o try.. except
raise Exception.Create( cstMsgSistemaFalhaEmpresasUsuarioLogado );
end;

Tem algum erro acontecendo e você não pega por causa disso.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Jan 13, 2012 3:36 pm    Assunto: Responder com Citação

Apenas para testes, reduzi toda a implementação do método para oq está abaixo. Mas continua dando o mesmo problema:

Código:
function TServerModuleEmpresa.GetUserCompanies(idUsuario: Integer; isMaster, isAdmin: Boolean): TDBXReader;
begin

  CDSEmpresas := CreateCDSEmpresas;

  // CDSEmpresas é um TClientDataSet com 4 registros...

  result := TDBXDataSetReader.Create( CDSEmpresas, False );

end;


result sempre retorna (nil,nil)
Ao que parece, o TDBXDataSetReader.Create não está funcionando e pode ser por duas coisas: Ou não funciona com um TClientDataSet ou está bugado para o XE =\
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
andreano
Novato
Novato


Registrado: Terça-Feira, 7 de Junho de 2005
Mensagens: 86

MensagemEnviada: Sex Jan 13, 2012 4:49 pm    Assunto: Responder com Citação

Se o DataSet tiver Blog não irá funcionar, o suporte a blog foi implementado no XE2
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Jan 13, 2012 4:50 pm    Assunto: Responder com Citação

andreano escreveu:
Se o DataSet tiver Blog não irá funcionar, o suporte a blog foi implementado no XE2

Não... não possui campos Blob. Apenas o padrão!
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sex Jan 13, 2012 4:53 pm    Assunto: Responder com Citação

Também realizei o teste colocando apenas 3 campos do ClientDataSet e mesmo assim, não funciona!

Código:
CDSEmpresas := TClientDataSet.Create( Self );

CDSEmpresas.FieldDefs.Add( 'id', ftInteger );
CDSEmpresas.FieldDefs.Add( 'nome', ftString, 40 );
CDSEmpresas.FieldDefs.Add( 'bloqueado', ftBoolean );

CDSEmpresas.CreateDataSet;

CDSEmpresas.Append;
CDSEmpresas.Fields[0].AsInteger := 1;
CDSEmpresas.Fields[1].AsString := 'Teste DBXReader';
CDSEmpresas.Fields[2].AsBoolean := False;
CDSEmpresas.Post;

result := TDBXDataSetReader.Create( CDSEmpresas, False );


result é sempre (nil,nil)


PS.: Se vale de alguma coisa, o método acima está dentro de um TDSServerModule
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
marcosalles
Moderador
Moderador


Registrado: Quarta-Feira, 26 de Março de 2008
Mensagens: 1695
Localização: Muriaé Mg

MensagemEnviada: Sáb Jan 14, 2012 11:11 am    Assunto: Responder com Citação

li este post desde de ontem é não é trivial resolver um problema a distancia
Mas teria jeito de ao invés de se utilizar um function com o retorno sendo
um clientDataSet , utilizar ao invés disso uma procedure cujo parâmetro
seje este ClientDataSet ...
_________________
http://marcosalles.wordpress.com

Desenvolvo FreeLancer e presto Consultoria
Orientação Online DataSnap DbX ClientDataSet
POO , Padrões de Projeto e dúvidas de Delphi em
Geral
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sáb Jan 14, 2012 3:56 pm    Assunto: Responder com Citação

marcosalles escreveu:
li este post desde de ontem é não é trivial resolver um problema a distancia
Mas teria jeito de ao invés de se utilizar um function com o retorno sendo
um clientDataSet , utilizar ao invés disso uma procedure cujo parâmetro
seje este ClientDataSet ...


Até teria sim! O problema é que o retorno não é um ClientDataSet e sim um DBXReader.
Na verdade, oq realmente preciso é de um ClientDataSet temporário na aplicação cliente. Apenas para consulta de alguns pouquíssimos dados pelo usuário, sem nenhum tipo de edição.

O melhor jeito que encontrei foi o recurso de DBXReaders mas, não funciona! E se até o Andreano aparentemente não sabe explicar o motivo, estou começando a ficar desestimulado com o DBXReader =((
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
marcosalles
Moderador
Moderador


Registrado: Quarta-Feira, 26 de Março de 2008
Mensagens: 1695
Localização: Muriaé Mg

MensagemEnviada: Sáb Jan 14, 2012 4:07 pm    Assunto: Responder com Citação

Eu quando precisei popular um clientDataset eu fiz e consegui bons
resultados segundo esta experiência

http://marcosalles.wordpress.com/2011/07/03/executar-stored-procedures-com-parametros-e-copiar-a-estrutura-e-dados-do-dbxreader-para-clientdataset-parte-vi/
_________________
http://marcosalles.wordpress.com

Desenvolvo FreeLancer e presto Consultoria
Orientação Online DataSnap DbX ClientDataSet
POO , Padrões de Projeto e dúvidas de Delphi em
Geral
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sáb Jan 14, 2012 4:10 pm    Assunto: Responder com Citação

marcosalles escreveu:
Eu quando precisei popular um clientDataset eu fiz e consegui bons
resultados segundo esta experiência

http://marcosalles.wordpress.com/2011/07/03/executar-stored-procedures-com-parametros-e-copiar-a-estrutura-e-dados-do-dbxreader-para-clientdataset-parte-vi/

Estou dando uma olhada nesse momento! Dando certo, aviso aqui! Wink
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
JCMF
Profissional
Profissional


Registrado: Quarta-Feira, 28 de Abril de 2010
Mensagens: 578
Localização: Recife, PE

MensagemEnviada: Sáb Jan 14, 2012 4:14 pm    Assunto: Responder com Citação

Solução muito interessante marcosalles!
A única diferença é que no meu caso, o cliente não define nenhum tipo de instrução SQL.

Oq realmente queria era algo a partir do código "Leitor:=Fcommand.ExecuteQuery;"... Ou seja, o meu cliente executa o método e recupera o "leitor", no formato DBXReader e depois é executado o CopyReaderToClientDataSet de forma super parecida com a sua implementação.

Existe uma forma de se fazer isso mas, utilizando o Fcommand.ExecuteUpdate e recuperando o DBXReader via Value.GetDBXReader?

Algo desse jeito:
Código:
  DBXCommand := DataSnapConnection.DBXConnection.CreateCommand;
  DBXCommand.CommandType := TDBXCommandTypes.DSServerMethod;

  DBXCommand.Text := 'TServerModuleEmpresa.GetUserCompanies';
  DBXCommand.Prepare;
  DBXCommand.Parameters[0].Value.SetInt32( usuario.Id );
  DBXCommand.Parameters[1].Value.SetBoolean( usuario.Master );
  DBXCommand.Parameters[2].Value.SetBoolean( usuario.Administrador );

  DBXCommand.ExecuteUpdate;

  DBXLeitor := DBXCommand.Parameters[3].Value.GetDBXReader( True );

  TDBXDataSetReader.CopyReaderToClientDataSet( DBXLeitor, cdsSelecao );

Não sei se estou conseguindo me fazer entender mas... dentro do método TServerModuleEmpresa.GetUserCompanies, o DBXReader é criado e retornado.
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário MSN Messenger
marcosalles
Moderador
Moderador


Registrado: Quarta-Feira, 26 de Março de 2008
Mensagens: 1695
Localização: Muriaé Mg

MensagemEnviada: Sáb Jan 14, 2012 10:48 pm    Assunto: Responder com Citação

Para piorar , comigo eu não tive nenhum problema .

Consegui conexão e popular o cdsSelecao na aplicação cliente

Claro utilizando sua simplificação

Citação:
CDSEmpresas := TClientDataSet.Create( Self );
CDSEmpresas.FieldDefs.Add( 'id', ftInteger );
CDSEmpresas.FieldDefs.Add( 'nome', ftString, 40 );
CDSEmpresas.FieldDefs.Add( 'bloqueado', ftBoolean );
CDSEmpresas.CreateDataSet;
CDSEmpresas.Append;
CDSEmpresas.Fields[0].AsInteger := 1;
CDSEmpresas.Fields[1].AsString := 'Teste DBXReader';
CDSEmpresas.Fields[2].AsBoolean := False;
CDSEmpresas.Post;
result := TDBXDataSetReader.Create( CDSEmpresas, False );


Citação:
procedure TForm8.Button1Click(Sender: TObject);
var
DBXReader:TDBXReader;
DBXCommand:TDBXCommand;
DBXLeitor:TdbxReader;
begin
DBXCommand := DataSnap_Ajuda_JCMF.DBXConnection.CreateCommand;
DBXCommand.CommandType := TDBXCommandTypes.DSServerMethod;
DBXCommand.Text := 'TServerMethods1.GetUserCompanies';
DBXCommand.Prepare;
DBXCommand.Parameters[0].Value.SetInt32(1 );
DBXCommand.Parameters[1].Value.SetBoolean(true );
DBXCommand.Parameters[2].Value.SetBoolean(true );
DBXCommand.ExecuteUpdate;
DBXLeitor := DBXCommand.Parameters[3].Value.GetDBXReader( True );
TDBXDataSetReader.CopyReaderToClientDataSet( DBXLeitor, cdsSelecao );
end;

_________________
http://marcosalles.wordpress.com

Desenvolvo FreeLancer e presto Consultoria
Orientação Online DataSnap DbX ClientDataSet
POO , Padrões de Projeto e dúvidas de Delphi em
Geral
Voltar ao Topo
Ver o perfil de Usuários Enviar Mensagem Particular Visitar a homepage do Usuário
Mostrar os tópicos anteriores:   
Novo Tópico   Responder Mensagem    ActiveDelphi - Índice do Fórum -> Delphi Todos os horários são GMT - 3 Horas
Ir à página 1, 2  Próximo
Página 1 de 2

 
Ir para:  
Enviar Mensagens Novas: Proibido.
Responder Tópicos Proibido
Editar Mensagens: Proibido.
Excluir Mensagens: Proibido.
Votar em Enquetes: Proibido.


Powered by phpBB © 2001, 2005 phpBB Group
Traduzido por: Suporte phpBB