Delphi DataSnap: Copiando dados para bases locais com Array DML

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.

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.

Listagem 1. Função para buscar os dados do servidor

public
  function GetClientes(): TFDJSONDataSets;
end;
function TServerMethods1.GetClientes: TFDJSONDataSets;
begin
  FDQuery1.Active := False;
  FDQuery1.SQL.Add('select idcliente, nome, genero, escolaridade from clientes');
  Result := TFDJSONDataSets.Create;
  TFDJSONDataSetsWriter.ListAdd(Result, FDQuery1);
end;

      

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.

Figura 2. Interface gráfica da aplicação cliente
Listagem 2. Cópia dos dados do servidor para o cliente

procedure TForm2.Button1Click(Sender: TObject);
var
  dsClientes: TFDJsonDataSets;
  qryInsercao: TFDQuery;
  inserts: Integer;
begin
  dsClientes := ClientModule1.ServerMethods1Client.GetClientes();
  if TFDJSONDataSetsReader.GetListCount(dsClientes) = 1 then
  begin
    FDMemTable1.Active := false;
    FDMemTable1.AppendData(TFDJSONDataSetsReader.GetListValue(dsClientes, 0));
    inserts := FDMemTable1.RecordCount;
    qryInsercao := TFDQuery.Create(Self);
    qryInsercao.Connection := FDConnection1;
    qryInsercao.SQL.Add('insert into clientes values (:id, :nome, :genero, :escolaridade)');
    qryInsercao.Params.ArraySize := inserts;
    while not FDMemTable1.Eof do
    begin
      qryInsercao.ParamByName('id').AsInteger := FDMemTable1.FieldByName('idcliente').AsInteger;
      qryInsercao.ParamByName('nome').AsString := FDMemTable1.FieldByName('nome').AsString;
      qryInsercao.ParamByName('genero').AsString := FDMemTable1.FieldByName('genero').AsString;
      qryInsercao.ParamByName('escolaridade').AsInteger := FDMemTable1.FieldByName('escolaridade').AsInteger;
      FDMemTable1.Next;
    end;
    qryInsercao.Execute(inserts, 0);
  end;
end;

      

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.

Artigos relacionados