Array
(
)

ClientDataSet - LookUp/Gravar/Ler - Cache Máquina Cliente

Userba
   - 05 dez 2005

Olá pessoal!

Estou utilizando DBExpress... delphi7/query/provider/clientdataset/firebird.

A título de exemplo:

-> usuario_nivel
-> usuario

Na tabela -> usuario_nivel ... tenho os campos

un_chave -> 1, 2, 3, ...
... mais campos
un_nivel -> administrador, técnico, desenvolvedor, ...

na tabela -> usuario ... tenho os campos

usu_chave -> 1, 2, 3, ...
... mais campos
un_chave (ligação com usuario_nivel) -> 1, 2, 3...

Para buscas de dados em tabelas que conténham muitos dados, pretendo chamar uma tela só para a pesquisa (utilizar sql e recuperar a chave_primária) e trazer para o form que chamou, a chave primária localizada, e posicionar o registro para permitir ediçao... etc, etc.... :)

Mas... Como os campos da tabela citada no exemplo acima -> ´usuario_nivel´, praticamente não mudam os valores, gostaria de saber se é melhor fazer um lookup utilizando um dblookupcombobox (me informaram que todos os dados são trazidos do servidor quando se utiliza o dblookcupcombox) ou se tem como fazer isto vindo de um ´arquivo que ficaria em cache nas máquinas cliente?.

Tipo -> Algo como um SavetoFile/Loadfromfile... :)
Enfim... Esse tipo de cache com ClientDataSet eu não sei se é ´possível fazer´ e ´como fazer´ :) para que eu possa utilizar com o ´dblookupcombox´ de uma maneira mais eficaz/rápida.

Se for possível criar este cache, pretendo utilizar a mesma técnica para outras ligações/lookups que retornam poucos dados ou dados que pouco mudam...

Tipo -> Outras tabelas auxiliares tais como: profissao, estado civil, cidades, sexo, etc.

* aproveito ainda para perguntar :)
* se é possivel ler e gravar em cache
* como eu faço para detectar/atualizar neste cache
* possíveis atualizações de dados caso ocorram
* nas tabelas auxiliares que estão no banco/servidor firebird?

desculpem a carta :)

Grato pelas Ajudas...
Luciano-User-BA


Raserafim
   - 06 dez 2005

sim, o cache é perfeitamente possível. e esta é uma boa técnica.
ao abrir a aplicação no cliente vc abre tb o ClientDataSet:
#Código

ClientDataSet.Open

neste momento o CLientDataSet vai abrir a query que o ProviderDataSet está associado e trazer os registros, depois vai fechar automaticamente a query. agora os dados vão ficar sempre em memória, e no cliente, assim os dados são acessados muito rapidamente. vc pode fazer isso tb, por exemplo, em uma tabela bairros.


0
|
0

Raserafim
   - 06 dez 2005

mas como saber se os dados foram alterados na base e informar isso a todas as aplicações clientes eu tb quero saber.


0
|
0

Emerson
   - 06 dez 2005


Citação:
Mas... Como os campos da tabela citada no exemplo acima -> ´usuario_nivel´, praticamente não mudam os valores, gostaria de saber se é melhor fazer um lookup utilizando um dblookupcombobox (me informaram que todos os dados são trazidos do servidor quando se utiliza o dblookcupcombox) ou se tem como fazer isto vindo de um ´arquivo que ficaria em cache nas máquinas cliente?.

Tipo -> Algo como um SavetoFile/Loadfromfile... :)

numa edição anterior da revista ClubeDelphi - não lembro qual - é abordado esse tema. a sugestão é a seguinte: seu clientdataset com dados ´estrangeiros´ (lookup) estará preparado para abrir um xml que conterá as informações. vamos chamá-lo de ´niveis_usuario.xml´.
você criará uma rotina para procurar pelo arquivo. caso não o encontre ou caso a data de criação ultrapasse 5 dias (ou quantos dias você queira) você traz os dados novamente e sobrepõe o xml. então, antes de abrir o clientdataset, você sempre deve executar a tal rotina.
dessa forma, durante esses 5 dias os dados estarão nesse xml, sem a necessidade de leitura no banco de dados.
você também pode colocar um botão para forçar a atualização dessas informações no momento em que o usuário desejar.


Citação:
* aproveito ainda para perguntar :)
* se é possivel ler e gravar em cache
* como eu faço para detectar/atualizar neste cache
* possíveis atualizações de dados caso ocorram
* nas tabelas auxiliares que estão no banco/servidor firebird?

- claro. quando você utiliza ClientDataset´s, tudo está sendo feito em cache. as informações somente serão gravadas fisicamente após um ApplyUpdates sem erros.
- isso pode ser feitos através de [url=http://www.borland.com/resources/en/pdf/white_papers/ib_events.pdf]eventos[/url].


0
|
0

Userba
   - 06 dez 2005


Citação:
a sugestão é a seguinte: seu clientdataset com dados ´estrangeiros´ (lookup) estará preparado para abrir um xml que conterá as informações. vamos chamá-lo de ´niveis_usuario.xml´. você criará uma rotina para procurar pelo arquivo. caso não o encontre ou caso a data de criação ultrapasse 5 dias (ou quantos dias você queira) você traz os dados novamente e sobrepõe o xml. então, antes de abrir o clientdataset, você sempre deve executar a tal rotina. dessa forma, durante esses 5 dias os dados estarão nesse xml, sem a necessidade de leitura no banco de dados. você também pode colocar um botão para forçar a atualização dessas informações no momento em que o usuário desejar.


Valeu... Já fiz uns testes e funcionou legal.

*** Utilizei o parametro -> dfXMLUTF8 para que pudesse gravar/ler os dados acentuados corretamente.

no oncreate do form:

if fileexists(´niveis_usuario.xml´) then dm_usuario.cds_nivel.LoadFromFile(´niveis_usuario.xml´);

dm_usuario.cds_nivel.Open;

if not fileexists(´niveis_usuario.xml´) then dm_usuario.cds_nivel.SaveToFile(´niveis_usuario.xml´, dfXMLUTF8);


Citação:
* aproveito ainda para... como eu faço para atualizar este cache caso ocorram atualizações nas tabelas auxiliares que estão no banco/servidor firebird?


É que... por não saber como funcionava o processo não soube me explicar :)


Citação:
claro. quando você utiliza ClientDataset´s, tudo está sendo feito em cache. as informações somente serão gravadas fisicamente após um ApplyUpdates sem erros.- isso pode ser feito através de eventos


... O que eu queria saber era se depois de utilizado um ´savetofile´, o clientedataset poderia comparar/identificar possíveis alterações nos dados que estão na base de dados no servidor com o arquivo XML criado na máquina cliente e promover a atualização automaticamente.

Mas acho que vc já deu as respostas :) Tenho que fazer isto manualmente... vou adaptar a rotina para detectar um prazo na data de criação e disponibilizar um button para atualizar manualmente, conforme suas sugestões.

* Aproveitando para esclarecer :) ... Quando o LoadFromFile é executado o clientdataset mostra os dados do arquivo XML (observei isto). Isto quer dizer que o SQLQuery ou SQLDataSet nem abre? Hummm... Se funcina assim... Isso é bom mesmo.

* Eu estava por fora dos metódos SAVE... LOAD...FILE, XMLs, etc... do clientedataset.

Valeu cara... Sua dica foi 10.

Luciano-User-BA


0
|
0

Userba
   - 06 dez 2005


Citação:
a sugestão é a seguinte: seu clientdataset com dados ´estrangeiros´ (lookup) estará preparado para abrir um xml que conterá as informações. vamos chamá-lo de ´niveis_usuario.xml´. você criará uma rotina para procurar pelo arquivo. caso não o encontre ou caso a data de criação ultrapasse 5 dias (ou quantos dias você queira) você traz os dados novamente e sobrepõe o xml. então, antes de abrir o clientdataset, você sempre deve executar a tal rotina. dessa forma, durante esses 5 dias os dados estarão nesse xml, sem a necessidade de leitura no banco de dados. você também pode colocar um botão para forçar a atualização dessas informações no momento em que o usuário desejar.


Valeu... Já fiz uns testes e funcionou legal.

*** Utilizei o parametro -> dfXMLUTF8 para que pudesse gravar/ler os dados acentuados corretamente.

no oncreate do form:

if fileexists(´niveis_usuario.xml´) then dm_usuario.cds_nivel.LoadFromFile(´niveis_usuario.xml´);

dm_usuario.cds_nivel.Open;

if not fileexists(´niveis_usuario.xml´) then dm_usuario.cds_nivel.SaveToFile(´niveis_usuario.xml´, dfXMLUTF8);


Citação:
* aproveito ainda para... como eu faço para atualizar este cache caso ocorram atualizações nas tabelas auxiliares que estão no banco/servidor firebird?


É que... por não saber como funcionava o processo não soube me explicar :)


Citação:
claro. quando você utiliza ClientDataset´s, tudo está sendo feito em cache. as informações somente serão gravadas fisicamente após um ApplyUpdates sem erros.- isso pode ser feito através de eventos


... O que eu queria saber era se depois de utilizado um ´savetofile´, o clientedataset poderia comparar/identificar possíveis alterações nos dados que estão na base de dados no servidor com o arquivo XML criado na máquina cliente e promover a atualização automaticamente.

Mas acho que vc já deu as respostas :) Tenho que fazer isto manualmente... vou adaptar a rotina para detectar um prazo na data de criação e disponibilizar um button para atualizar manualmente, conforme suas sugestões.

* Aproveitando para esclarecer :) ... Quando o LoadFromFile é executado o clientdataset mostra os dados do arquivo XML (observei isto). Isto quer dizer que o SQLQuery ou SQLDataSet nem abre? Hummm... Se funcina assim... Isso é bom mesmo.

* Eu estava por fora dos metódos SAVE... LOAD...FILE, XMLs, etc... do clientedataset.

Valeu cara... Sua dica foi 10.

Luciano-User-BA


0
|
0

Emerson
   - 06 dez 2005

é isso mesmo.
você configura seu ClientDataset normalmente: ProviderName, CommandText, etc. e, em FileName, coloca o nome do arquivo xml desejado. depois você cria uma rotina mais ou menos assim (não testei):
#Código

procedure TForm1.AbreDatasetXML( var Dataset: TClientDataset );
var
NomeArquivo: string;
CriaArquivo: boolean;
begin
NomeArquivo := Dataset.FileName;
Dataset.Close;

if NomeArquivo <> ´´ then
begin
if FileExists(NomeArquivo) then
// se existe o arquivo, verifico se ele tem mais de 5 dias
CriaArquivo := Trunc(Now - FileDateToDateTime(FileAge(NomeArquivo))) > 5
else
CriaArquivo := True;

if CriaArquivo then
begin
Dataset.FileName := ´´; // limpa o nome do arquivo e abre o dataset
Dataset.Open; // com as informações do CommandText/ProviderName
Dataset.SaveToFile(NomeArquivo, dfXMLUTF8);
Dataset.Close;
Dataset.FileName := NomeArquivo;
end;

Dataset.Open;
end;
end;

aí, vc abre os clientdatasets xml a partir dessa procedure.
AbreDatasetXML( ClientDataset_UsuarioNiveis );

se o clientdataset tiver um arquivo informado na sua propriedade FileName, a procedure se encarrega de todo o processo.


0
|
0

Userba
   - 06 dez 2005


Citação:
é isso mesmo. você configura seu ClientDataset normalmente: ProviderName, CommandText, etc. e, em FileName, coloca o nome do arquivo xml desejado. depois você cria uma rotina ...


É ... Com uma função assim, o código fica centralizado, precisando passar apenas o ClientDataSet como parâmetro. Vou colocar num module que abre os CDS auxiliares e testar, se não funcionar eu posto aqui, senão... o pessoal já fica sabendo que sua dica funciona beleza.

Cara! brigadão mesmo pelas dicas... E pela função de brinde :).

Luciano-User-BA


0
|
0