Componentes de Acesso a Banco de Dados.

Firebird

06/09/2004

Colegas, inicio aqui uma discussão a respeito da melhor forma de acessar tabelas num banco. Uso Delphi6 com Firebird-1.5.1.4481;
Uso componentes IBX . . . tabelas com o IbDataSet e DataSource e consulta com o IbQuery; No Datamodule um IbDataBase e um IbTransaction e ainda auto-incremento com Generator;
Até parece que funciona bem no entanto quando inseridos registros nas tabelas as estações não ´enxergam´ as atualizações em tempo real, uso CommitRetaining já que Commit fecha as tabelas e teria que abri-las todas novamente.
Nunca usei os componentes DbExpress, não sei se seria a melhor escolha . . . ouvi dizer de um pacote de componentes IBO(não tenho certeza se é esse o nome), assim gostaria da opinião de todos que se interessarem a respeito . . .


Amilton/pr

Amilton/pr

Curtidas 0

Respostas

Afarias

Afarias

06/09/2004

|Até parece que funciona bem no entanto quando inseridos registros nas
|tabelas as estações não ´enxergam´ as atualizações em tempo real,

Configure as transações (IBTransaction) para READ COMMITED (Dê um duplo-clique no componente)



T+


GOSTEI 0
Vinicius2k

Vinicius2k

06/09/2004

Apenas acrescentando ao que o afarias colocou, lembre-se ainda de que vc está trabalhando com dados em cache de memória, e uma estação não vai ´ver´ os uptates realizados por outra até que seja dado um Refresh ou Close/Open no DataSet ou Query...

Sobre os componentes, neste aspecto não existem grandes diferenças... o controle está baseado em como estão configuradas as suas transações...
dbExpress(DBX) é uma opção pela portabilidade (ao menos teórica) de uma aplicação entre vários bancos... IBO é bom (difícil, mas bom), mas o FIB+ é melhor (na minha opinião), o porém é que ambos são pagos...

Eu trabalhei um bom tempo com IBX e não tenho nada a reclamar... estou trabalhando com DBX agora... no início a idéia era tornar a aplicação facilmente portável substituindo um driver, mas não é tão simples assim...

Como o DBX é unidirecional, fui ´forçado´ a utilizar a Midas (Provider + ClientDataSet) e foi aí que eu percebi que não precisaria estar mudando para o DBX... :(
O que eu pretendia, na verdade, que era ter facilidade em portar a camada inteira sem grandes mudanças no código, poderia ser obtido com IBX + Midas... se vc basear todo o desenvolvimento do acesso aos dados em cima da Midas, a camada de acesso propriamente dita, pode ser qualquer uma... e é relativamente fácil substituir a camada se vc não basear grande quantidade de código sobre ela...

T+


GOSTEI 0
Amilton/pr

Amilton/pr

06/09/2004

O componente IbTransaction já está configurado como ReadCommited;

Na navegação de registros faço assim:
DtsPac.Dataset.Refresh;
e mesmo assim(na estação) não mostra o registro inserido em outra máquina; Sobre abrir e fechar a tabela eu não tentei nenhuma vez porque meu raciocionio era de que fechar a tabela e mesmo abrindo em seguida poderia causar algum efeito no usuário que estiver inserindo algum dado na mesma tabela em outra máquina, estou errado?

Sobre o midas achei que deveria haver um registro do Midas para o uso do DBX . . . como é o desenvolvimento de acesso a dados com midas?


GOSTEI 0
Vinicius2k

Vinicius2k

06/09/2004

[quote:5f5c4c73ca=´Amilton/Pr´]Sobre abrir e fechar a tabela eu não tentei nenhuma vez porque meu raciocionio era de que fechar a tabela e mesmo abrindo em seguida poderia causar algum efeito no usuário que estiver inserindo algum dado na mesma tabela em outra máquina, estou errado?[/quote:5f5c4c73ca]
Sim. Vc estah errado. Abrir e fechar a query, é apenas solicitar novamente os dados ao servidor. Não tem qualquer influencia, a não ser aumento de tráfego na rede, sobre as outras estações, mas julgo ser um ´mal´ necessário... Em condições ´normais´ um Refresh tem o mesmo efeito de um Close/Open, mas lembre-se de que nenhuma das duas formas surtirá efeito se a transação envolvida na inserção do registro por outra estação não for ´commitada´... afinal, apenas o Commit da transação efetiva o registro no Banco de Dados...

[quote:5f5c4c73ca=´Amilton/Pr´]Sobre o midas achei que deveria haver um registro do Midas para o uso do DBX . . . [/quote:5f5c4c73ca]
Como assim registro? Se vc está falando do seu tópico anterior, onde sugeri que vc registrasse a midas.dll como DLL do sistema, é porque ela é necessária quando se trabalha com ClientDataSets e vc estava na dúvida se existiam ou não IBClientDataSets na sua aplicação. Lembra-se? Foi só por isso... trabalhando com IBX sem Providers e ClientDataSets ela não é necessária.
Como no DBX vc é, praticamente, obrigado a usar Providers e ClientDataSets quando deseja uma interface mais amigável com o usuário (navegação bidirecional) e maior facilidade para trabalhar o projeto, a presença da midas.dll é obrigatória...

[quote:5f5c4c73ca=´Amilton/Pr´]como é o desenvolvimento de acesso a dados com midas?[/quote:5f5c4c73ca]
A diferença é que a inserção, edição e deleção dos registros é feita no ClientDataSet, com métodos conhecidos como Append, Edit, Post, Delete, etc... terminada a atualização, vc invoca o método ´ApplyUpdates´ que irá enviar as atualizações ao Provider e este, por sua vez, irá interagir com a camada de acesso para efetivar as atualizações no Banco de Dados...
O ClientDataSet permite, até mesmo, a presença de ´CommandText´, que é a instrução SQL a ser executada, um ´Select´ por exemplo, o que lhe permite ter uma IBQuery, SQLQuery ou ADOQuery, apenas pré-configuradas as conexões, sem nenhuma instrução... ela será totalmente comandada pelo Provider, daí vem a facilidade numa eventual substituição da camada de acesso...
Eu ainda estou ´engatinhando´ na midas, mas estou convencido de que é uma tecnologia muito, mas muito, útil...

T+


GOSTEI 0
Amilton/pr

Amilton/pr

06/09/2004

Ufa!!! até que enfim esse link funcionou . . . foram dois dias fora do ar.

Seguinte . . .
Mostro os registros da tabela num DbNavigator, No Evento onclick tem esse código:
If button in[nbfirst,nblast,nbprior,nbnext] then
begin
DtsPac.Dataset.Refresh;
edit1.text:=TblPacNumero.AsString;
edit3.text:=TblPacN_Hygia.AsString;
mostra1();
end;

Assim o registro inserido numa máquina não mostra em tempo real na outra, se eu abrir e fechar a tabela o registro não sai do primeiro porque quando abro ele vai sempre pro primeiro registro, teria então que fazer o tratamento, ou seja, armazenar o código acrescentar +1 e quando abrir pesquisa por esse registro, mas não seria um processo a mais a ser executado ao invés de simplesmente ir pro registro seguinte?


GOSTEI 0
Vinicius2k

Vinicius2k

06/09/2004

:shock:
Posso ser franco? Não entendi nada do que vc disse...
Ou estou meio lerdo hoje ou vc pensou mais rápido do que escreveu... :D

Explique-se melhor...

T+


GOSTEI 0
Amilton/pr

Amilton/pr

06/09/2004

No formulário de Cadastro tenho um componente DbNavigator ligado ao Datasource do IbDataSet, com os botões para mover entre os registros, inserir, apagar, etc. certo?
No Evento OnClick desse componente coloquei o código acima para os botões first, last, prior e next, ou seja, mover entre os registros e ai dei um refresh na tabela; acontece que quando dois usuários usam o mesmo formulário pra cadastrar, uma máquina não ´vê´ o registro que o outro inseriu(mesmo dando o refresh) então testei fechando e abriando a tabela no entanto ficou pior ainda pois quando a tabela é aberta vai sempre para o primeiro registro então nunca sai do primeiro pois o processo de fechar e abrir se repete e continua no primeiro registro . . .


GOSTEI 0
Afarias

Afarias

06/09/2004

|acontece que quando dois usuários usam o mesmo formulário pra
|cadastrar, uma máquina não ´vê´ o registro que o outro inseriu

O q é natural. Visto q os registros q vc está vendo estão em um buffer, e os usuários da rede estão inserindo/alterando o banco de dados q está no servidor.


|(mesmo dando o refresh)

Refresh no IBX apenas atualiza o registro selecionado. Não serve para atualizar os demais registros ou ´trazer´ novos registros adicionados no banco.


|então testei fechando e abriando a tabela

Correto. Esta é a única forma.


|no entanto ficou pior ainda pois quando a tabela é aberta vai sempre
|para o primeiro registro então nunca sai do primeiro pois o processo de
|fechar e abrir se repete e continua no primeiro registro . .

Não entendi aqui... acho q isso tem a ver com o seu código... algum evento mal colocado ou algo assim.

Quanto a ir para o 1º registro, o q vc pode fazer é antes de fechar a tabela pegue o código do registro selecionado, entào feche, abra e então dê um locate no código ´anotado´ anteriormente.

Mas preste atenção, ficar fechando/abrindo um DataSet não é algo muito eficiente... avalie se não pode dar uma solução melhor para este processo q está desenvolvendo -- tenha em mente que está programando um sistema C/S


T+


GOSTEI 0
Vinicius2k

Vinicius2k

06/09/2004

Agora eu entendi...

No Evento OnClick desse componente coloquei o código acima para os botões first, last, prior e next, ou seja, mover entre os registros e ai dei um refresh na tabela...

:shock: Cara, isso é loucura... se o select do seu IBDataSet retornar um volume grande de registros vc vai ´matar´ a performance da sua aplicação e vai ficar difícil até mesmo para o usuário navegar... acho q vc deve repensar isto.

uma máquina não ´vê´ o registro que o outro inseriu(mesmo dando o refresh)

volto a questionar : para que o usuário B veja o registro inserido pelo usuário A, a transação utilizada para inserir o registro no usuário A tem que ter sido commitada (IBTransaction.Commit ou IBTransaction.CommitRetainning)... vc está certo de que está fazendo isso?
Se sim vc precisa Abrir e Fechar para buscar os dados novamente e, se julgar necessário, reposicionar o cursor da DBGrid no registro selecionado anteriormente...
Mas vc precisa analisar bem quando fazer isso... se vc ficar abrindo e fechando o DataSet o tempo todo sua aplicação vai ficar muito lenta e vai aumentar muito o tráfego na rede...

Eu trabalho assim, na maioria dos casos (depende do volume de registros) : eu fecho e abro o DataSet em 3 ocasiões : ao inserir , ao editar e ao deletar, no mais, se o usuário quiser ver os dados atualizados, tenho um botão ´Atualizar´ q fecha e abre o DataSet, mas fica a critério dele... não deixo isso ´no automático´...

T+


GOSTEI 0
Amilton/pr

Amilton/pr

06/09/2004

Entendi . . . coloquei um botão a mais pra atualizar a tabela e aí eu abro e fecho a tabela somente uma vez e realmente os dados são atualizados; acho que por enquanto enquanto é a melhor solução; Não quis ficar colocando códigos pra navegar entre registros, acho que poderia comprometer a performance do sistema, embora tenha mantido o Refresh nos botões de navegação.
Engraçado é que uso o CommitRetaining para gravar os registros e depois abro a tabela novamente e mesmo assim não atualiza a base toda na rede;
Não uso somente o Commit porque parece que fecha todas as tabelas e depois eu teria que abri-las novamente, se usasse o Commit poderia ser resolvido isso facilmente?


GOSTEI 0
Afarias

Afarias

06/09/2004

|Engraçado é que uso o CommitRetaining para gravar os registros e
|depois abro a tabela novamente e mesmo assim não atualiza a base
|toda na rede;

Tem algo errado ai. Uma vez efetuado o commitretaining (ou o commit) os registros atualizados ficam disponíveis para serem lidos por qualquer outra transação em ´read commited´


|se usasse o Commit poderia ser resolvido isso facilmente?

Em relação a disponibilizar alterações para outros clientes na rede, não há diferença entre usar commit ou commitretaining


T+


GOSTEI 0
Amilton/pr

Amilton/pr

06/09/2004

Uso esse código pra gravar:

procedure Tf_pacientes.BitBtn5Click(Sender: TObject);
begin
try
tblPac.Edit;
DtsPac.DataSet.Post;
TblPac.Transaction.commitRetaining; //Retaining;
TblPac.active:=True;
edit1.enabled:=False;
edit1.text:=TblPacNumero.AsString;
except
showmessage(´Não foi possível gravar o registro!´);
end;
end;

Tem algo errado aí?


GOSTEI 0
Afarias

Afarias

06/09/2004

O q esse código faz?? Pra mim ele não faz nada!! :?


|tblPac.Edit;
|DtsPac.DataSet.Post;

edit/post! pra q serve isso??

|TblPac.Transaction.commitRetaining; //Retaining;
|TblPac.active:=True;

Porque o active=true se a tabela não está sendo fechada

|edit1.enabled:=False;
|edit1.text:=TblPacNumero.AsString;

vc sabe em q registro está?

|except
|showmessage(´Não foi possível gravar o registro!´);
|end;

gravar o q?



T+


GOSTEI 0
Amilton/pr

Amilton/pr

06/09/2004

Realmente algumas coisas são vicios . . .
No entanto cabe algumas explicações:

Esse código grava o cadastro de pacientes o qual o número é mostrado somente quando confirmado nesse botão, então esse o motivo de ser mostrado num edit;
tblPac.Edit; // Não precisa
DtsPac.DataSet.Post; // sem essa linha o valor do código não é
mostrado no edit.
TblPac.active:=True; // Realmente não precisa
edit1.text:=TblPacNumero.AsString; // coloquei no AfterPost da
Tabela.

Mensagem: // Realmente precisa melhorar.

Gostaria de sugestões da melhor forma de realizar esse procedimento.


GOSTEI 0
POSTAR