Guia Programação Web com Delphi

Delphi DataSnap: Copiando dados para bases locais com Array DML

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (5)  (0)

Veja neste artigo como copiar dados de um servidor de aplicação DataSnap para uma aplicação cliente local utilizando o recurso Array DML.

Motivação

Quando desenvolvemos aplicativos mobile, estes podem ter dois tipos de armazenamento: uma base de dados nativa, que fica localizada no próprio aparelho, ou então uma base localizada em um servidor de aplicação em um servidor externo. Nesse último caso, é necessário que o dispositivo esteja conectado à Internet para ter acesso às funções do software. Hoje em dia, uma outra alternativa bastante comum é manter duas bases de dados, ou seja, uma no aparelho e outra no servidor. Dessa forma, o usuário pode continuar trabalhando no aplicativo localmente e quando houver disponibilidade de conexão, seus dados locais podem ser transferidos para o servidor ou então os dados atualizados do servidor podem ser copiados para a base local.

Servidores DataSnap são um exemplo de tecnologia que pode ser utilizada para esse fim e, dentro desse contexto é importante conhecer as maneiras que permitem essa sincronização entre cliente e servidor. A execução chamada de Array DML é uma técnica que submete uma única instrução em SQL para a inserção de novos dados, utilizando um vetor de parâmetros que contém os novos registros. Essa técnica reduz a quantidade de comunicação entre o servidor e o cliente, o que garante uma melhor velocidade no tempo de execução dos comandos.

Passo 1: Criando o método no servidor

Para este exemplo, devemos criar uma nova aplicação DataSnap e dentro da unit ServerMethodsUnit adicionar os componentes de acesso a dados para buscar os registros no banco. Para isso, serão necessários quatro componentes: FDConnection, FDQuery, FDPhysMSSQLDriverLink e FDStanStorageJSONLink. O primeiro é utilizado para realizar a conexão com a base, o segundo para executar a instrução SQL, o terceiro representa o driver de acesso ao SGBD (sistema gerenciador de banco de dados) e, por fim, o último diz respeito ao formato de dados que trafegará pela rede (neste caso, arquivos). A Figura 1 apresenta esses componentes.

Componentes de acesso a dados
Figura 1. Componentes de acesso a dados

Além disso, é também necessário um método remoto nesta mesma unit para que os dados sejam retornados para a aplicação cliente. Seu código pode ser visto na Listagem 1.

01 public
02   function GetClientes(): TFDJSONDataSets;
03 end;
04 function TServerMethods1.GetClientes: TFDJSONDataSets;
05 begin
06   FDQuery1.Active := False;
07   FDQuery1.SQL.Add('select idcliente, nome, genero, escolaridade from clientes');
08   Result := TFDJSONDataSets.Create;
09   TFDJSONDataSetsWriter.ListAdd(Result, FDQuery1);
10 end;
Listagem 1. Função para buscar os dados do servidor

Linhas 01, 02 e 03: Definição da função GetClientes() dentro da seção public da unit. O tipo de retorno do método é TFDJSONDataSets e na cláusula uses do arquivo o namespace Data.FireDACJSONReflect deve ser declarado;

Linha 06: A query é fechada para a execução de um novo comando;

Linha 07: Definimos o comando em SQL para buscar os dados tabela de clientes;

Linha 08: Criamos o objeto que armazenará o resultado da consulta;

Linha 09: Utilizando a classe TFDJSONDataSetsWriter, adicionamos à lista de retorno a variável Result, passando como parâmetro o componente <FDQuery1, para que os dados relativos à consulta SQL sejam retornados.

Passo 2: Criando o método no cliente

A Figura 2 apresenta a interface gráfica da aplicação cliente, a qual é composta somente um um botão (TButton) e três componentes: FDConnection, que realiza a conexão com uma base de dados local; FDMemTable, que representa uma tabela em memória e que receberá os dados do servidor; e FDStanStorageJSONLink, para receber os dados no formato JSON. Em aplicações mobile, o componente de conexão pode estar ligado a uma base no SQLite, que é comumente utilizada para esse tipo de aplicativo. Quando o botão for clicado, os dados do servidor serão carregados na tabela em memória (FDMemTable1) e depois será feito o insert em massa para inserir todos os registros na base de dados local. O código da Listagem 2 apresenta esse processo, o qual é definido no evento OnClick do botão.

Interface gráfica da aplicação cliente
Figura 2. Interface gráfica da aplicação cliente

01 procedure TForm2.Button1Click(Sender: TObject);
02 var
03   dsClientes: TFDJsonDataSets;
04   qryInsercao: TFDQuery;
05   inserts: Integer;
06 begin
07   dsClientes := ClientModule1.ServerMethods1Client.GetClientes();
08   if TFDJSONDataSetsReader.GetListCount(dsClientes) = 1 then
09   begin
10     FDMemTable1.Active := false;
11     FDMemTable1.AppendData(TFDJSONDataSetsReader.GetListValue(dsClientes, 0));
12     inserts := FDMemTable1.RecordCount;
13     qryInsercao := TFDQuery.Create(Self);
14     qryInsercao.Connection := FDConnection1;
15     qryInsercao.SQL.Add('insert into clientes values (:id, :nome, :genero, :escolaridade)');
16     qryInsercao.Params.ArraySize := inserts;
17     while not FDMemTable1.Eof do
18     begin
19       qryInsercao.ParamByName('id').AsInteger := FDMemTable1.FieldByName('idcliente').AsInteger;
20       qryInsercao.ParamByName('nome').AsString := FDMemTable1.FieldByName('nome').AsString;
21       qryInsercao.ParamByName('genero').AsString := FDMemTable1.FieldByName('genero').AsString;
22       qryInsercao.ParamByName('escolaridade').AsInteger := FDMemTable1.FieldByName('escolaridade').AsInteger;
23       FDMemTable1.Next;
24     end;
25     qryInsercao.Execute(inserts, 0);
26   end;
27 end;
Listagem 2. Cópia dos dados do servidor para o cliente

Linha 03: Declaramos a variável dataset do tipo TFDJSONDataSets, que armazena os registros carregados do servidor. É necessário informar na cláusula uses do formulário as units Data.FireDACJSONReflect e ClientModuleUnit1;

Linha 04: Definimos a variável do tipo FDQuery para executar as inserções na base de dados local;

Linha 05: Declaramos uma varíavel do tipo inteiro que armazenará a quantidade de registros que foram retornados do servidor;

Linha 07: Invocamos o método GetClientes, declarado no servidor e acessado por meio da unit ClientModule1. A variável dsClientes receberá todos os registros provenientes da consulta SQL executada no servidor;

Linha 08: Verificamos se algum dataset foi retornado do servidor, para posteriormente executar a cópia dos registros;

Linhas 10, 11 e 12: Desativamos a tabela em memória, copiamos os dados do servidor para ela e então a variável inserts recebe a quantidade de registros retornados;

Linhas 13, 14 e 15: Criamos a query em tempo de execução, a associamos ao componente de conexão e definimos o comando insert para inserir os dados, recebendo quatro parâmetros (id, nome, genero e escolaridade);

Linha 16: A propriedade ArraySize da query recebe a quantidade de registros que serão inseridos por meio de Array DML;

Linhas 17 a 24: Por meio de uma estrutura de repetição, percorremos a tabela em memória registro por registro e associamos os parâmetros da query de inserção aos respectivos valores da memory table;

Linha 25: Por meio do comando execute, executamos todos os comandos de

Com isso, temos uma estrutura que primeiramente faz a leitura dos registros do servidor e posteriormente os insere em uma base de dados local. Conforme mecionado anteriormente, esse código pode ser utilizado para sincronizar aplicação cliente e servidora, mantendo-as atualizadas.

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Ficou com alguma dúvida?