Uso pleno do TClientDataSet e o Modelo de Maleta

Qualidade: 

Estrela ativaEstrela ativaEstrela ativaEstrela ativaEstrela ativa
 

Páginas neste artigo

O TClientDataSet stand-alone (MyBase)

O TClientDataSet stand-alone é a solução perfeita para situações em que são necessários executáveis autônomos, sem a necessidade de instalar mecanismos de banco de dados adicionais ou drivers. Como o TClientDataSet carrega todos os dados na memória ele é muito rápido, mas o tamanho das tabelas é limitado à quantidade de memória disponível (e o tempo de carga/persistência de dados também aumenta correspondentemente). Além disso, não podemos executar consultas SQL, mas filtros e outras operações podem ser realizadas.

Por que um TClientDataSet local?

Os benefícios da utilização do TClientdataSet como um DataSet local sobre, por exemplo, o BDE são numerosos. Em primeiro lugar, o TClientdataSet está contido dentro de uma única DLL chamada MIDAS.DLL. Apenas soltá-la dentro do diretório Windows\System1 (ou deixá-la no mesmo diretório que o executável Delphi) e você está apto a usar o componente. A partir do Delphi 6, você pode até mesmo adicionar a unit MidasLib à cláusula uses do arquivo .dpr do seu projeto. Ao fazer isso, toda a biblioteca MIDAS.DLL será incorporada dentro do seu executável (que irá crescer cerca de 200K), resultando em um verdadeiro executável autônomo de configuração-zero! Compare isto com a instalação do BDE no seu computador cliente. E mesmo que você decida usar ado2, por exemplo, que provavelmente já estará disponível na máquina do seu cliente, você precisará garantir que o banco de dados a acessar (Access, SQL Server, etc.) também esteja presente, funcional e com as bibliotecas de acesso (client libraries) disponíveis. Em suma, o MIDAS.DLL é provavelmente um dos "bancos de dados" mais fáceis de instalar que você já viu até então!

O TClientDataSet é também uma das implementações de DataSet mais rápidas que existem. Classificação e filtragem são feitas com uma velocidade impressionante. Com toda essa velocidade então ele é um componente perfeito, não é? Não é bem assim! Essa velocidade toda tem um custo alto e é também uma das desvantagens potenciais do TClientDataSet. Tudo é gerenciado na memória, e cada operação, como classificação, filtragem ou busca também é feito na memória. Isso explica a velocidade, mas também significa que um TClientDataSet com uma grande quantidade de dados exige uma grande quantidade de memória em sua máquina.

Está gostando do que está lendo? Ajude nosso site visitando nossos patrocinadores. Obrigado! :)

Alimentando um TClientDataSet local...

A maneira mais fácil de carregar um TClientDataSet em tempo de design, é clicar com o botão direito no componente TClientDataSet e selecionar a opção do menu pop-up "Assign local data". Isto irá mostrar uma caixa de diálogo que lista todos os conjuntos de dados (tabelas, consultas, etc.) disponíveis no TForm atual ou em um TDataModule associado. Ao escolher um item nessa lista e pressionar OK, todos os dados do conjunto de dados escolhido serão atribuídos ao TClientDataSet e você poderá então remover o conjunto de dados fonte do TForm ou TDataModule, ficando apenas com um TClientDataSet stand-alone que contém todos os dados do conjunto de dados de origem. Note que você ainda precisará remover a unit DBTables caso você esteja usando o BDE e quiser fazer sua aplicação totalmente independente do BDE.

Além de usar a opção "Assign Local Data", um TClientDataSet também pode carregar e armazenar suas informações no disco. Isto é visível em tempo de design pelas opções "Load From File" e "Save To File" do menu pop-up3. O componente TClientDataSet em si contém também estes métodos acessíveis em tempo de execução, bem como os métodos LoadFromStream e SaveToStream, que você pode redirecionar a diferentes tipos de fluxos (como um TMemoryStream, imediatamente antes de enviar esse fluxo através de uma conexão socket, por exemplo).

O TClientDataSet pode carregar e armazenar dois tipos de formato de dados. O primeiro é normalmente chamado formato "cds", e é o formato binário interno (e não documentado). Pequeno, nativo e quase impossível de compartilhar (exceto com outros componentes TClientDataSet de Delphi 5 e superior, C ++ Builder 5 e superiores, e Kylix). O segundo formato de dados que o TClientDataSet suporta é o XML, e todos nós sabemos que arquivos XML são abertos, independentes de plataforma e portáteis, no entanto, o formato XML que é usado pelo TClientDataSet ainda é um formato proprietário definido originalmente pela Borland, por isso não é fácil usá-lo com um conjunto de dados ADO, por exemplo.

Usando um TClientDataSet local...

Uma vez que um TClientDataSet local é preenchido com dados, nós podemos navegar por ele como qualquer outro conjunto de dados, no entanto há uma diferença que pode ser um benefício ou uma maldição (se você não estiver ciente disso). A principal diferença entre o TClientDataSet e outros conjuntos de dados tradicionais (TTable ou similares) é o fato de o TClientDataSet não salvar automaticamente o seu conteúdo em disco. E mesmo se isso acontecer, ele só salva as alterações que tiverem sido realizadas e não o conjunto de dados completos (dados antigos mais dados alterados).

O que isso significa exatamente, e como podemos fazer melhor uso desta funcionalidade? Primeiro de tudo, vamos dar uma olhada nas capacidades de salvamento do TClientDataSet. Se os dados dentro do TClientDataSet são carregados por quaisquer outros meios que não a propriedade FileName do TClientDataSet, então ele, obviamente, não sabe onde guardar os dados que tenham sido modificados (os dados originais devem ter sido carregados a partir do arquivo .dfm). Se a propriedade FileName for usada, então o TClientDataSet vai salvar o seu conteúdo de volta para o arquivo quando ele for explicitamente desativado (close) (ou destruído). No entanto, em algumas situações, pode ser uma boa ideia chamar explicitamente o método SaveToFile (assim como você teria de usar LoadFromFile para carregar os novos dados de volta).

Agora, se você usar LoadFromFile no início da sua aplicação, e SaveToFile no final da mesma, então você vai perceber que o arquivo externo (com o conteúdo do TClientDataset) cresce a uma taxa mais elevada do que seria esperado de poucas mudanças e possíveis adições que você faça no TClientDataSet. Algo está acontecendo dentro desse arquivo e se você o salvar no formato XML, então você descobrirá rapidamente que todas as alterações individuais são salvas, tanto com o valor "original" como com o valor "alterado" de cada registro. Isto significa que mesmo poucas mudanças vão encher o banco de dados rapidamente com várias versões de registros com alterações, que ocupam mais espaço do que as próprias alterações em si (ou as alterações aplicadas ao conjunto de dados).

Por que isso é feito? Basicamente, para permitir que o TClientDataSet trabalhe em um ambiente multi-tier (e multi-utilizador). Em um ambiente multi-camadas, o TClientDataSet precisa chamar o método ApplyUpdates, o qual envia as atualizações pendentes para a camada de conjunto de dados remoto (middleware) e isto tem de incluir tanto a versão original dos registros, como as alterações que serão aplicadas. Se a versão original de um registro não coincide com a versão atual do registro (persistido em banco de dados), a atualização pode não ser aplicada. Este é um problema típico de ambientes multi-usuários que precisa ser resolvido para evitar problemas de integridade de dados, mas ao usar o TClientDataSet como uma solução stand-alone este comportamento é muito indesejado.

E fica ainda pior quando você percebe que o TClientDataSet contém o valor original de todos os registros, bem como todas as alterações, o que significa que quando você carregar o arquivo externo, terá que voltar a aplicar todas as alterações e isto levará tempo, tornando a carga mais e mais lenta com o tempo, à medida que mais e mais mudanças são aplicadas.

MegeChangeLog

Felizmente existe um método especial chamado MergeChangeLog, o qual faz, tal como o nome sugere, a mesclagem de todas as alterações contidas no TClientDataSet, o que resulta em um arquivo bem pequeno novamente (com apenas os registros e todas as mudanças efetivas aplicadas neles). Obviamente este método nunca deve ser executado em um ambiente multi-camadas, pois ele vai quebrar todas as possíveis chamadas ao método ApplyUpdates que você queira fazer. Contudo, em um ambiente de camada única local, este método é estritamente necessário, pois ele diminui o tamanho (e acelera o carregamento) da representação local do TClientDataSet.

Antes de executar o método MergeChangeLog, é recomendável verificar o valor de ChangeCount, que representa o número de alterações que estão atualmente disponíveis no TClientDataSet. Apenas se ChangeCount for maior que zero é que você deve executar o método MergeChangeLog, do contrário isso seria apenas perda de tempo.

Como uma última dica, você pode querer considerar o fato de que um log de modificações inclui a habilidade para "desfazer" alterações registro a registro usando os métodos UndoLastChange, CancelUpdates ou RevertRecord. Leia a ajuda do Delphi para maiores detalhes. Estes métodos podem também ser usados em um ambiente multi-camadas, claro, antes de se executar um ApplyUpdates.

e-max.it: your social media marketing partner
1Atualmente o mais indicado é usar os diretórios System32 ou SysWOW64
2Ou qualquer outro tipo de componente de conexão que não exija instalação na máquina-cliente, como o FireDAC, o UniDAC, o ZeosLib, etc.
3Os nomes dos itens deste menu variam de acordo com o Delphi sendo utilizado. No Delphi 2006, por exemplo, existem os itens Load from MyBase table..., Save to MyBase XML table..., Save to MyBase XML UTF8 Table... e Save to Binary MyBase file...
Ajude nosso site visitando nossos patrocinadores!

Temos 96 visitantes e Nenhum membro online nos últimos 10 minutos (9.6 visitantes por minuto).