Manter Dataset aberto condicionalmente
Pessoal,
Estou modificando algumas coisas aqui num sistema, visando principalmente permitir o acesso a diversos forms simultaneamente ou não, porém estou com um problema. Uso sempre DataModule para armazenar os datasets e datasources (IBX) de praticamente tudo nos meus sistemas, apenas algumas poucas queries coloco no próprio form que a usa.
Normalmente ao abrir um form, eu abro os dm.datasets que serão usados por ele, e ao fechar o form eu fecho os datasets abertos. Porém um mesmo dataset, lá do DM, também é aberto por outro form, que por sua vez também o fecha ao sair... Mas e o form que ficou aberto que e continua precisando daquelas informações? O que faço?
Pensei em usar a propriedade TAG do dataset para armazenar um número referente ao primeiro form que abriu o dataset e somente fechar o dataset se o pedido de fechamento viesse deste mesmo form, os demais não fechariam o dataset se o ´dono´ dele, informado na propriedade tag do dataset, fosse outro.
Porém isso fica muito numérico para meu gosto (cada form teria que ser identificado por um número para ser colocado nessas tags), então pensei em criar variáveis globais no DM, uma para cada dataset, armazenando sempre que um dataset for aberto o nome do form ´dono´. E sempre que algum form for fechar o dataset verificar se dono do dataset é ele próprio, senão, não fecha o dataset.
Será que deu pra entender? Será que estou pensando corretamente ou viajei na maionese... O que me recomendariam fazer nestes casos?
Estou modificando algumas coisas aqui num sistema, visando principalmente permitir o acesso a diversos forms simultaneamente ou não, porém estou com um problema. Uso sempre DataModule para armazenar os datasets e datasources (IBX) de praticamente tudo nos meus sistemas, apenas algumas poucas queries coloco no próprio form que a usa.
Normalmente ao abrir um form, eu abro os dm.datasets que serão usados por ele, e ao fechar o form eu fecho os datasets abertos. Porém um mesmo dataset, lá do DM, também é aberto por outro form, que por sua vez também o fecha ao sair... Mas e o form que ficou aberto que e continua precisando daquelas informações? O que faço?
Pensei em usar a propriedade TAG do dataset para armazenar um número referente ao primeiro form que abriu o dataset e somente fechar o dataset se o pedido de fechamento viesse deste mesmo form, os demais não fechariam o dataset se o ´dono´ dele, informado na propriedade tag do dataset, fosse outro.
Porém isso fica muito numérico para meu gosto (cada form teria que ser identificado por um número para ser colocado nessas tags), então pensei em criar variáveis globais no DM, uma para cada dataset, armazenando sempre que um dataset for aberto o nome do form ´dono´. E sempre que algum form for fechar o dataset verificar se dono do dataset é ele próprio, senão, não fecha o dataset.
Será que deu pra entender? Será que estou pensando corretamente ou viajei na maionese... O que me recomendariam fazer nestes casos?
Aerreira
Curtidas 0
Respostas
Bon Jovi
26/10/2005
O ideal que acho é que cada form deve usar uma instância diferente deste data module. Ou seja, tirar do auto create e criar/destruir em cada form o data module. Nao esquecendo também de apagar a variavel global de unit que o Delphi escreve de forma nao OO (var DataModule1: TDataModule1;). Cada classe de form deverá ter uma variavel privada para a instância do data module.
Outras coisas:
Ter um único data module pra tudo num sistema médio ou grande pode ficar confuso. Pra alguns conjuntos de regras de negócio é bom separar. E particularmente acho mais legal usar classes TObject em conjunto com datamodule.
DataSource acho melhor ficar melhor no Form.
Outras coisas:
Ter um único data module pra tudo num sistema médio ou grande pode ficar confuso. Pra alguns conjuntos de regras de negócio é bom separar. E particularmente acho mais legal usar classes TObject em conjunto com datamodule.
DataSource acho melhor ficar melhor no Form.
GOSTEI 0
Bon Jovi
26/10/2005
[i:9816be9088]Cada classe de form deverá ter uma variavel privada para a instância do data module. [/i:9816be9088]
Complementando: com isso terá que setar o Connection e demais objetos em tempo de execução se quiser chamar de outra classe.
Complementando: com isso terá que setar o Connection e demais objetos em tempo de execução se quiser chamar de outra classe.
GOSTEI 0
Anfm
26/10/2005
Eu costumo criar uma cópia do datamodule para cada form.
Para fazer isto faça o seguinte:
No uses da sua unit declare o unit do datamodule;
Na seção private declare uma variável que receberá a cópia do datamodule: DMLocal : TDataModule;
No on create do seu form coloque:
DMLocal := TDataModule.Create(Self)
DataSource1.DataSet := DMLocal.NomeTabela;
Para fazer isto faça o seguinte:
No uses da sua unit declare o unit do datamodule;
Na seção private declare uma variável que receberá a cópia do datamodule: DMLocal : TDataModule;
No on create do seu form coloque:
DMLocal := TDataModule.Create(Self)
DataSource1.DataSet := DMLocal.NomeTabela;
GOSTEI 0
Aerreira
26/10/2005
DMLocal := TDataModule.Create(Self)
DataSource1.DataSet := DMLocal.NomeTabela;
Fiz o que você falou: o datamodule já está no uses do form, declarei dmLocal em private, coloquei um DataSource no form e chamei de dsConv, e coloquei o código abaixo no oncreate do form:
dmLocal := TDataModule.Create(Self);
dsConv.dataset := dmLocal.tbConv;
O problema nesse caso é que não existe dmLocal.tbConv (leia-se tbConv como o DataSet que está no DM), o que existe sim é dm.tbConv, ou seja apenas a tabela no DM original e não em dmLocal. Não faltou alguma coisa aí não? Ligar o dmLocal ao dm real?
Como criar uma instância diferente do mesmo DM em cada form ?
Desculpem a ignorância, mas realmente não faço esse tipo de coisa.
GOSTEI 0
Aerreira
26/10/2005
[quote:e8554fd7f0=´Bon Jovi´]Nao esquecendo também de apagar a variavel global de unit que o Delphi escreve de forma nao OO (var DataModule1: TDataModule1;).[/quote:e8554fd7f0]
O problema acima é: se eu tiro o ´var dm: Tdm;´ do datamodule eu fico com tudo que o sistema atualmente se referencia a ´dm...´ sem funcionar, então não sei se o dmLocal funciona mesmo ou não... Pois no teste que fiz acima com dmLocal não funcionou. Será que é porque ainda tenho o ´var dm: Tdm´ lá no datamodule ?
O problema acima é: se eu tiro o ´var dm: Tdm;´ do datamodule eu fico com tudo que o sistema atualmente se referencia a ´dm...´ sem funcionar, então não sei se o dmLocal funciona mesmo ou não... Pois no teste que fiz acima com dmLocal não funcionou. Será que é porque ainda tenho o ´var dm: Tdm´ lá no datamodule ?
GOSTEI 0
Anfm
26/10/2005
Então,
Onde vc está criando o Data Module local
vc tem q se referenciar ao DataModule que vc já possui, ou seja, vc vai criar uma cópia dele com todos componentes que ele possui.
Suponhamos q o seu DataModule chame dmtabelas,
então vc deve criar da seguinte maneira:
A unit que contém o DataModule deve ser colocado no uses principal da Unit, onde estão as units forms, dialogs, etc.
Onde vc está criando o Data Module local
dmLocal := TDataModule.Create(Self);
vc tem q se referenciar ao DataModule que vc já possui, ou seja, vc vai criar uma cópia dele com todos componentes que ele possui.
Suponhamos q o seu DataModule chame dmtabelas,
então vc deve criar da seguinte maneira:
dmLocal := Tdmtabelas.Create(Self);
A unit que contém o DataModule deve ser colocado no uses principal da Unit, onde estão as units forms, dialogs, etc.
GOSTEI 0
Aerreira
26/10/2005
Suponhamos q o seu DataModule chame dmtabelas,
então vc deve criar da seguinte maneira:
A unit que contém o DataModule deve ser colocado no uses principal da Unit, onde estão as units forms, dialogs, etc.
dmLocal := Tdmtabelas.Create(Self);
Meu DataModule chama-se ´dm´, então tentei:
dmLocal := Tdm.Create(Self);
dsConv.dataset := dmLocal.tbConv;
Resultado: Undeclared Identifier na segunda linha
Outro teste (o que eu estava fazendo antes):
dmLocal := TDataModule.Create(Self);
dsConv.dataset := dmLocal.tbConv;
Resultado: o mesmo erro na segunda linha.
O nome da unit do DataModule é ´datamodule´ e o nome do form é ´dm´. Fiz os testes acima com o ´datamodule´ no uses após implementation, e também colocando no uses lá de cima, após interface. Não funcionou em nenhuma das duas situações.
Tá faltando alguma coisa... mas não sei o que.
GOSTEI 0
Firekiller
26/10/2005
Você poderia trabalhar com a sua idéia inicial de trabalhar com as tags... mas a cada form que abrisse (e que utilizasse o dataset), seria adicionado 1 na tag do dataset. Ao fechar o form, tira-se 1 da tag do dataset. Se o dataset estiver com a tag = 0 então, ele deve ser fechado, senão não. É uma forma mais simples de implementar o que já estava pronto.
Eu particularmente, trabalho com vários datamodules. Por exemplo, para o form de cadastro de clientes, tenho um datamodule que contem 1 dataset para conexão com a tabela de clientes. Para o form de vendas, tenho um datamodule com 1 dataset para a tabela vendas, 1 para Itens, 1 para Produtos e 1 para Clientes. Dessa forma aplico as regras que desejo para cada datamodule individualmente.
Para facilitar (quando devo abrir o que), crio procedimentos dentro do datamodule do tipo Abrir e Fechar, assim, para abrir o que preciso de um datamodule faço:
DmClientes.Abrir;
ou
DmClientes.Fechar;
Normalmente, antes de criar esses datamodules, crio um datamodule matriz que dará origem a todos os outros, nele é que coloco esse tipo de função, então trato, cada um de acordo com a necessidade. Assim, não preciso ficar criando instancias do datamodule dentro do sistema.
Eu particularmente, trabalho com vários datamodules. Por exemplo, para o form de cadastro de clientes, tenho um datamodule que contem 1 dataset para conexão com a tabela de clientes. Para o form de vendas, tenho um datamodule com 1 dataset para a tabela vendas, 1 para Itens, 1 para Produtos e 1 para Clientes. Dessa forma aplico as regras que desejo para cada datamodule individualmente.
Para facilitar (quando devo abrir o que), crio procedimentos dentro do datamodule do tipo Abrir e Fechar, assim, para abrir o que preciso de um datamodule faço:
DmClientes.Abrir;
ou
DmClientes.Fechar;
Normalmente, antes de criar esses datamodules, crio um datamodule matriz que dará origem a todos os outros, nele é que coloco esse tipo de função, então trato, cada um de acordo com a necessidade. Assim, não preciso ficar criando instancias do datamodule dentro do sistema.
GOSTEI 0
Aerreira
26/10/2005
Você poderia trabalhar com a sua idéia inicial de trabalhar com as tags... mas a cada form que abrisse (e que utilizasse o dataset), seria adicionado 1 na tag do dataset. Ao fechar o form, tira-se 1 da tag do dataset. Se o dataset estiver com a tag = 0 então, ele deve ser fechado, senão não. É uma forma mais simples de implementar o que já estava pronto.
Taí, gostei da sua ideia de usar o tag para controlar ´quantos´ abriram o dataset e não ´quem´ como eu havia pensado, simplifica tudo, basta ir incrementando ao abrir e diminuindo ao pedir para fechar, mas realmente só fechar quando o tag estiver em 0.
Acredito que isso irá funcionar, mas fiquei curioso em ver a situação passada pelo ANFM e pelo BON JOVI com relação a criação instâncias locais para o DataModule, pena que ainda não funcionou... Alguem saberia dizer o que ainda está errado ?
GOSTEI 0
Bon Jovi
26/10/2005
O modo mais simples:
Melhorando..
//Project1.dpr program Project1; uses Forms, Unit1 in ´Unit1.pas´ , Unit2 in ´Unit2.pas´ {DataModule1: TDataModule}; {$R *.RES} var Form1: TForm1; begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. //Form... //Unit1.pas unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, Unit2, Grids, DBGrids; type TForm1 = class(TForm) DataSource1: TDataSource; DBGrid1: TDBGrid; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } DataModule1: TDataModule1; public { Public declarations } end; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin DataModule1 := TDataModule1.Create(nil); DataSource1.DataSet := DataModule1.ADODataSet1; end; procedure TForm1.FormDestroy(Sender: TObject); begin DataModule1.Free; end; end. //Unit1.DFM object Form1: TForm1 Left = 192 Top = 107 Width = 696 Height = 480 Caption = ´Form1´ OnCreate = FormCreate OnDestroy = FormDestroy object DBGrid1: TDBGrid Left = 4 Top = 4 Width = 320 Height = 120 DataSource = DataSource1 end object DataSource1: TDataSource Left = 328 Top = 4 end end //Data module... //Unit2.pas unit Unit2; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, ADODB; type TDataModule1 = class(TDataModule) ADOConnection1: TADOConnection; ADODataSet1: TADODataSet; private { Private declarations } public { Public declarations } end; implementation {$R *.DFM} end. //Unit2.DFM object DataModule1: TDataModule1 Left = 272 Top = 162 Height = 480 Width = 696 object ADOConnection1: TADOConnection Left = 40 Top = 20 end object ADODataSet1: TADODataSet Connection = ADOConnection1 Left = 124 Top = 20 end end
Melhorando..
//dpr program Project1; uses Forms, Unit1 in ´Unit1.pas´ , Unit2 in ´Unit2.pas´ {DataModule1: TDataModule}, Unit3 in ´Unit3.pas´; {$R *.RES} var Form1: TForm1; begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. //pas unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, Grids, DBGrids, Unit3; type TForm1 = class(TForm) DataSource1: TDataSource; DBGrid1: TDBGrid; procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormShow(Sender: TObject); private { Private declarations } Negocio1: TNegocio1; public { Public declarations } end; implementation {$R *.DFM} procedure TForm1.FormCreate(Sender: TObject); begin Negocio1 := TNegocio1.Create; end; procedure TForm1.FormDestroy(Sender: TObject); begin Negocio1.Free; end; procedure TForm1.FormShow(Sender: TObject); begin DataSource1.DataSet := Negocio1.Abre; end; end. //dfm object Form1: TForm1 Left = 192 Top = 107 Width = 696 Height = 480 Caption = ´Form1´ Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = ´MS Sans Serif´ Font.Style = [] OldCreateOrder = True OnCreate = FormCreate OnDestroy = FormDestroy OnShow = FormShow PixelsPerInch = 96 TextHeight = 13 object DBGrid1: TDBGrid Left = 4 Top = 4 Width = 320 Height = 120 DataSource = DataSource1 TabOrder = 0 TitleFont.Charset = DEFAULT_CHARSET TitleFont.Color = clWindowText TitleFont.Height = -11 TitleFont.Name = ´MS Sans Serif´ TitleFont.Style = [] end object DataSource1: TDataSource Left = 328 Top = 4 end end //pas unit Unit2; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Db, DbClient, ADODB, Provider; type TDataModule1 = class(TDataModule) ADOConnection1: TADOConnection; ADODataSet1: TADODataSet; ClientDataSet1: TClientDataSet; DataSetProvider1: TDataSetProvider; private { Private declarations } public { Public declarations } end; implementation {$R *.DFM} end. //dfm object DataModule1: TDataModule1 OldCreateOrder = True Left = 272 Top = 162 Height = 480 Width = 696 object ADOConnection1: TADOConnection Left = 40 Top = 20 end object ADODataSet1: TADODataSet Connection = ADOConnection1 Parameters = <> Left = 124 Top = 20 end object ClientDataSet1: TClientDataSet Aggregates = <> Params = <> ProviderName = ´DataSetProvider1´ Left = 292 Top = 20 end object DataSetProvider1: TDataSetProvider DataSet = ADODataSet1 Constraints = True UpdateMode = upWhereKeyOnly Left = 208 Top = 20 end end //pas unit Unit3; interface uses DbClient, Unit2; type TNegocio1 = class(TObject) private DataModule1: TDataModule1; public constructor Create; destructor Destroy; override; function Abre: TClientDataSet; procedure Fecha; end; implementation function TNegocio1.Abre: TClientDataSet; begin DataModule1.ClientDataSet1.Close; DataModule1.ADODataSet1.CommandText := ´SELECT...´; DataModule1.ClientDataSet1.Open; Result := DataModule1.ClientDataSet1; end; procedure TNegocio1.Fecha; begin DataModule1.ClientDataSet1.Close; end; constructor TNegocio1.Create; begin DataModule1 := TDataModule1.Create(nil); end; destructor TNegocio1.Destroy; begin DataModule1.Free; inherited; end; end.
GOSTEI 0
Aerreira
26/10/2005
Bom dessa vez funcionou com as explicações do BonJovi.
Estou testando em apenas um form da aplicação para ver se funciona, que usa apenas dois datasets, em linhas gerais o que mudou com as últimas explicações foi:
No form:
- a declaração do DataModule vai para o uses da Interface
- é criada a variável privada ´dmLocal: Tdm;´ (acho que era isso que estava faltando, lembrando que meu DataModule principal chama-se ´dm´)
- no OnCreate do form, vai a criação da instância local do DM: ´dmLocal := Tdm.Create(nil);´ mais a ligação dos DataSources aos DataSets do dmLocal: ´dsConv.dataset := dmLocal.tbConv;´ e ´dsTab.dataset := dmLocal.tbTab;´
- no OnShow do form, vai a abertura dos datasets ´dmLocal.tbConv.open;´ e ´dmLocal.tbTab.open;´
- no OnClose do form, vai o fechamento dos datasets ´dmLocal.tbConv.close;´ e ´dmLocal.tbTab.close;´
- no OnDestroy do form, libero o dmLocal da memória: ´dmLocal.free;´
No DataModule:
- não muda nada, apenas passarei a usar os DataSets dentro dos forms e não no datamodule.
Funcionou, pois outros forms que abrem os datasets do DM original, continuam abrindo e fechando enquanto o datasets do form de teste continua aberto, ou seja, está sendo usado o dmLocal de forma independente do DM principal.
Não usei as funções que você apresenta em seu segundo exemplo como Abre e Fecha. Falando em segundo exemplo, se eu entendi vc tem uma unit (unit2) para o datamodule e outra unit (unit3) para tratar a outra instância do datamodule e não no próprio form como no seu primeiro exemplo. É isso?
De qualquer modo, vou testar implementando os DM locais em vários forms e ver se funciona bem. Te agradeço pelas dicas.
Efeito colateral: quando a instância do DM é criada o OnCreate do datamodule é executado, e é lá que identifico a localização do banco e abro o IBDataBase... Isso está correto? Provavelmente com isso estou abrindo o banco totalmente independente como se fosse outra aplicação.
Uma questão: se eu tiver muitos forms abertos, cada um com uma instância do DM com vários datasets abertos... isso não vai sobrecarregar muito a memória não?
Estou testando em apenas um form da aplicação para ver se funciona, que usa apenas dois datasets, em linhas gerais o que mudou com as últimas explicações foi:
No form:
- a declaração do DataModule vai para o uses da Interface
- é criada a variável privada ´dmLocal: Tdm;´ (acho que era isso que estava faltando, lembrando que meu DataModule principal chama-se ´dm´)
- no OnCreate do form, vai a criação da instância local do DM: ´dmLocal := Tdm.Create(nil);´ mais a ligação dos DataSources aos DataSets do dmLocal: ´dsConv.dataset := dmLocal.tbConv;´ e ´dsTab.dataset := dmLocal.tbTab;´
- no OnShow do form, vai a abertura dos datasets ´dmLocal.tbConv.open;´ e ´dmLocal.tbTab.open;´
- no OnClose do form, vai o fechamento dos datasets ´dmLocal.tbConv.close;´ e ´dmLocal.tbTab.close;´
- no OnDestroy do form, libero o dmLocal da memória: ´dmLocal.free;´
No DataModule:
- não muda nada, apenas passarei a usar os DataSets dentro dos forms e não no datamodule.
Funcionou, pois outros forms que abrem os datasets do DM original, continuam abrindo e fechando enquanto o datasets do form de teste continua aberto, ou seja, está sendo usado o dmLocal de forma independente do DM principal.
Não usei as funções que você apresenta em seu segundo exemplo como Abre e Fecha. Falando em segundo exemplo, se eu entendi vc tem uma unit (unit2) para o datamodule e outra unit (unit3) para tratar a outra instância do datamodule e não no próprio form como no seu primeiro exemplo. É isso?
De qualquer modo, vou testar implementando os DM locais em vários forms e ver se funciona bem. Te agradeço pelas dicas.
Efeito colateral: quando a instância do DM é criada o OnCreate do datamodule é executado, e é lá que identifico a localização do banco e abro o IBDataBase... Isso está correto? Provavelmente com isso estou abrindo o banco totalmente independente como se fosse outra aplicação.
Uma questão: se eu tiver muitos forms abertos, cada um com uma instância do DM com vários datasets abertos... isso não vai sobrecarregar muito a memória não?
GOSTEI 0
Aerreira
26/10/2005
Bom, quanto ao tópico fiquei com duas opções:
- Usar instâncias diferentes do DataModule em cada form da aplicação;
ou
- Abrir os DataSets no próprio DataModule original, controlando pela propriedade TAG quantas vezes o dataset foi aberto, e fechar apenas quando o último form solicitar o fechamento.
As duas soluções estão funcionando, agora resta a dúvida: qual das duas funcionará melhor com a aplicação funcionando, com umas 20 estações de rede num banco com tamanho previsto de aproximadamente uns 200Mb (tamanho baseado na aplicação atual em DOS) ?
A primeira solução dá um isolamento total entre os forms, porém acho que poderá ocupar muita memória, talvez também gerar mais tráfego na rede por abrir e fechar o banco em cada form, e não sei quais poderão ser as conseguencias em máquinas pequenas.
A segunda solução mantém tudo ligado. Num teste que fiz, abri o mesmo form mais de uma vez e a navegação numa tabela ocorre simultaneamente nas duas telas, com a primeira solução isso não aconteceria.
Alguem poderia dar uma opinião para tirar essa minha dúvida?
- Usar instâncias diferentes do DataModule em cada form da aplicação;
ou
- Abrir os DataSets no próprio DataModule original, controlando pela propriedade TAG quantas vezes o dataset foi aberto, e fechar apenas quando o último form solicitar o fechamento.
As duas soluções estão funcionando, agora resta a dúvida: qual das duas funcionará melhor com a aplicação funcionando, com umas 20 estações de rede num banco com tamanho previsto de aproximadamente uns 200Mb (tamanho baseado na aplicação atual em DOS) ?
A primeira solução dá um isolamento total entre os forms, porém acho que poderá ocupar muita memória, talvez também gerar mais tráfego na rede por abrir e fechar o banco em cada form, e não sei quais poderão ser as conseguencias em máquinas pequenas.
A segunda solução mantém tudo ligado. Num teste que fiz, abri o mesmo form mais de uma vez e a navegação numa tabela ocorre simultaneamente nas duas telas, com a primeira solução isso não aconteceria.
Alguem poderia dar uma opinião para tirar essa minha dúvida?
GOSTEI 0
Bon Jovi
26/10/2005
[i:2ee3bad4cb]´se eu entendi vc tem uma unit (unit2) para o datamodule e outra unit (unit3) para tratar a outra instância do datamodule e não no próprio form como no seu primeiro exemplo. É isso?´[/i:2ee3bad4cb]
É por aí, faço assim pra separar totalmente a interface grafica do usuário com as regras de negócio e acesso ao servidor de banco de dados. Colocar o ClientDataSet direto no form também é correto.
[i:2ee3bad4cb]´Efeito colateral: quando a instância do DM é criada o OnCreate do datamodule é executado, e é lá que identifico a localização do banco e abro o IBDataBase... Isso está correto? Provavelmente com isso estou abrindo o banco totalmente independente como se fosse outra aplicação.´[/i:2ee3bad4cb]
Basta vc criar um DataModule só para a conexao, assim abrirá somente uma vez a conexão.
[i:2ee3bad4cb]´Uma questão: se eu tiver muitos forms abertos, cada um com uma instância do DM com vários datasets abertos... isso não vai sobrecarregar muito a memória não?´[/i:2ee3bad4cb]
Depende do ponto de vista, mas eu considero que não, pois estará usando recursos sob demanda, não terá nada aberto a toa e sem malabarismos de tags. E não deixe de usar ClientDataSet, senão realmente estará cutucando muito os servidor. Outra saída tb seria trabalhar com clonagem de ClientDataSet, mas só gosto de usar quando é extremamente necessário.
É por aí, faço assim pra separar totalmente a interface grafica do usuário com as regras de negócio e acesso ao servidor de banco de dados. Colocar o ClientDataSet direto no form também é correto.
[i:2ee3bad4cb]´Efeito colateral: quando a instância do DM é criada o OnCreate do datamodule é executado, e é lá que identifico a localização do banco e abro o IBDataBase... Isso está correto? Provavelmente com isso estou abrindo o banco totalmente independente como se fosse outra aplicação.´[/i:2ee3bad4cb]
Basta vc criar um DataModule só para a conexao, assim abrirá somente uma vez a conexão.
[i:2ee3bad4cb]´Uma questão: se eu tiver muitos forms abertos, cada um com uma instância do DM com vários datasets abertos... isso não vai sobrecarregar muito a memória não?´[/i:2ee3bad4cb]
Depende do ponto de vista, mas eu considero que não, pois estará usando recursos sob demanda, não terá nada aberto a toa e sem malabarismos de tags. E não deixe de usar ClientDataSet, senão realmente estará cutucando muito os servidor. Outra saída tb seria trabalhar com clonagem de ClientDataSet, mas só gosto de usar quando é extremamente necessário.
GOSTEI 0
Bon Jovi
26/10/2005
[i:293aefaf11]´um banco com tamanho previsto de aproximadamente uns 200Mb´[/i:293aefaf11]
Isso não importa, pode ser 10 GB, portanto que logicamente vc não traga todos os registros da tabela, e sim o necessário que o usuário quer consultar, geralmente um único registro.
Isso não importa, pode ser 10 GB, portanto que logicamente vc não traga todos os registros da tabela, e sim o necessário que o usuário quer consultar, geralmente um único registro.
GOSTEI 0
Aerreira
26/10/2005
[quote:86d7b7a7c8=´Bon Jovi´][i:86d7b7a7c8]´um banco com tamanho previsto de aproximadamente uns 200Mb´[/i:86d7b7a7c8]
Isso não importa, pode ser 10 GB, portanto que logicamente vc não traga todos os registros da tabela, e sim o necessário que o usuário quer consultar, geralmente um único registro.[/quote:86d7b7a7c8]
Certo, isso já uso, na medida do possível, por praxe, mas veja uma questão:
Uma tela de atendimento de pacientes, onde tenho os seguintes datasets abertos (uns para atualização outros apenas para consulta): pacientes, convênios, planos, medicos, especialidades, atendimentos, itens do atendimento, serviços, materiais, medicamentos, circulares e parâmetros, considerando todos visualizando apenas um registro. Ainda assim são 12 datasets abertos numa instancia do DM. Em outra tela o usuário abre uma agenda com mais uns 10 datasets, e ao mesmo tempo está gerando um determinado relatório com mais uns 5 datasets em outro DM.
Será que isso fica melhor usando a opção de DM locais ou abrindo tudo num único DM controlando os datasets abertos? O que pesa menos na rede e também em termos de memória nas estações?
Isso não importa, pode ser 10 GB, portanto que logicamente vc não traga todos os registros da tabela, e sim o necessário que o usuário quer consultar, geralmente um único registro.[/quote:86d7b7a7c8]
Certo, isso já uso, na medida do possível, por praxe, mas veja uma questão:
Uma tela de atendimento de pacientes, onde tenho os seguintes datasets abertos (uns para atualização outros apenas para consulta): pacientes, convênios, planos, medicos, especialidades, atendimentos, itens do atendimento, serviços, materiais, medicamentos, circulares e parâmetros, considerando todos visualizando apenas um registro. Ainda assim são 12 datasets abertos numa instancia do DM. Em outra tela o usuário abre uma agenda com mais uns 10 datasets, e ao mesmo tempo está gerando um determinado relatório com mais uns 5 datasets em outro DM.
Será que isso fica melhor usando a opção de DM locais ou abrindo tudo num único DM controlando os datasets abertos? O que pesa menos na rede e também em termos de memória nas estações?
GOSTEI 0
Bon Jovi
26/10/2005
A cada tela que o usuário for abrir, possivelmente ele vai querer acessar os dados mais atualizados, com filtros diferentes e particularidades que possam sempre vir a surgir nessa outra tela.
Se as máquinas estão tão apertadas assim de recursos e as linhas acessadas são sempre as mesmas em diversos lugares (o que não entendo pq), use então clonagem de ClientDataSets, onde vai abrir os dados uma vez e cada clone terá navegação independente.
Se as máquinas estão tão apertadas assim de recursos e as linhas acessadas são sempre as mesmas em diversos lugares (o que não entendo pq), use então clonagem de ClientDataSets, onde vai abrir os dados uma vez e cada clone terá navegação independente.
GOSTEI 0
Aerreira
26/10/2005
[quote:79892ffd83=´Bon Jovi´]A cada tela que o usuário for abrir, possivelmente ele vai querer acessar os dados mais atualizados, com filtros diferentes e particularidades que possam sempre vir a surgir nessa outra tela.
[/quote:79892ffd83]
Certo.
[quote:79892ffd83=´Bon Jovi´]Se as máquinas estão tão apertadas assim de recursos e as linhas acessadas são sempre as mesmas em diversos lugares (o que não entendo pq), use então clonagem de ClientDataSets, onde vai abrir os dados uma vez e cada clone terá navegação independente.[/quote:79892ffd83]
Não que as máquinas estejam apertadas, mas tenho a sensação de que os DM locais irão gerar muitos objetos em memória (cada DM com todos os componentes que ele tem, conexão, transaction, datasets, ´datasources´ sim porque não), enquanto na outra solução haveria um único DM a ser tratado. Não uso ClientDataSet e sim IBDataSet pois uso IBX/Delphi5.
Não entendi seu questionamento ´[i:79892ffd83]as linhas acessadas são sempre as mesmas em diversos lugares (o que não entendo pq)[/i:79892ffd83]´.
Como assim as mesmas linhas? Você quer dizer registros das tabelas? Em diversos lugares sim, como não? O usuário pode estar registrando informações sobre o atendimento de um paciente, em outra tela estar consultando / incluindo novos apontamentos na agenda de um médico, que também está atendendo o paciente da primeira tela, e ao mesmo tempo estar extraindo um relatório relativo aos atendimentos do mesmo médico no dia anterior... Isso é a realidade do negócio... Tudo ao mesmo tempo sim.. porque não... por isso a mesma informação (médico) é tratada em vários pontos ao mesmo tempo... porque não seria assim?
[/quote:79892ffd83]
Certo.
[quote:79892ffd83=´Bon Jovi´]Se as máquinas estão tão apertadas assim de recursos e as linhas acessadas são sempre as mesmas em diversos lugares (o que não entendo pq), use então clonagem de ClientDataSets, onde vai abrir os dados uma vez e cada clone terá navegação independente.[/quote:79892ffd83]
Não que as máquinas estejam apertadas, mas tenho a sensação de que os DM locais irão gerar muitos objetos em memória (cada DM com todos os componentes que ele tem, conexão, transaction, datasets, ´datasources´ sim porque não), enquanto na outra solução haveria um único DM a ser tratado. Não uso ClientDataSet e sim IBDataSet pois uso IBX/Delphi5.
Não entendi seu questionamento ´[i:79892ffd83]as linhas acessadas são sempre as mesmas em diversos lugares (o que não entendo pq)[/i:79892ffd83]´.
Como assim as mesmas linhas? Você quer dizer registros das tabelas? Em diversos lugares sim, como não? O usuário pode estar registrando informações sobre o atendimento de um paciente, em outra tela estar consultando / incluindo novos apontamentos na agenda de um médico, que também está atendendo o paciente da primeira tela, e ao mesmo tempo estar extraindo um relatório relativo aos atendimentos do mesmo médico no dia anterior... Isso é a realidade do negócio... Tudo ao mesmo tempo sim.. porque não... por isso a mesma informação (médico) é tratada em vários pontos ao mesmo tempo... porque não seria assim?
GOSTEI 0
Bon Jovi
26/10/2005
´a sensação de que os DM locais irão gerar muitos objetos em memória (cada DM com todos os componentes que ele tem´.
Sim, cada um com sua área de memória.
´conexão, transaction´
Como disse anteriormente, vc pode criar um DataModule só pra conexão e instancia-lo uma única vez.
´´datasources´ sim porque não´
DataSource serve pra ligar componentes visuais, ao ClientDataSet de preferência, então devem estar do lado cliente/interface gráfica com o usuário.
´Não uso ClientDataSet e sim IBDataSet pois uso IBX/Delphi5´
Mantendo IBDataSet abertos diretamente pro usuário em DBGrids ou DBCombos por exemplo podem gerar muito mais idas e voltas ao servidor do que o ClientDataSet (que pode ficar totalmente desconectado). Delphi 5 tb tem o ClientDataSet, podendo ser usado com o IBX.
Sobre esses dados de um médico, aí sim poderiam ficar em um único DataSet, pois não há navegação por ser uma única linha. Assim como poderiam ficar em variáveis. Caso contrário, clone.
Sim, cada um com sua área de memória.
´conexão, transaction´
Como disse anteriormente, vc pode criar um DataModule só pra conexão e instancia-lo uma única vez.
´´datasources´ sim porque não´
DataSource serve pra ligar componentes visuais, ao ClientDataSet de preferência, então devem estar do lado cliente/interface gráfica com o usuário.
´Não uso ClientDataSet e sim IBDataSet pois uso IBX/Delphi5´
Mantendo IBDataSet abertos diretamente pro usuário em DBGrids ou DBCombos por exemplo podem gerar muito mais idas e voltas ao servidor do que o ClientDataSet (que pode ficar totalmente desconectado). Delphi 5 tb tem o ClientDataSet, podendo ser usado com o IBX.
Sobre esses dados de um médico, aí sim poderiam ficar em um único DataSet, pois não há navegação por ser uma única linha. Assim como poderiam ficar em variáveis. Caso contrário, clone.
GOSTEI 0
Aerreira
26/10/2005
Ok, pela questão do isolamento entre as operações, estou optando por instanciar os DMs localmente em cada form. E sim (obrigado pela dica), vou criar um outro DM apenas para a conexão com o banco (ex: dmCON) e ligar os datasets do DM principal (e suas instâncias locais) ao dmCON.DB e dmCON.TRAN.
Com relação aos DataSources, já li pessoas dizerem que é apenas uma questão de preferência e organização, muitos fazem como vc diz, porém muitos dizem ser errado, pois mistura coisas que deveriam estar em outro local, na prática, não muda nada. Prefiro manter as coisas mais organizadas deixando os datasources ao lado dos datasets, se eu precisar de algo um pouco diferente, aí sim coloco um datasource no form e trabalho com ele separado, mas como agora terei DMs proprios para cada form, faço com eles o que for necessário em cada instanciamento, mas mantenho os datasources no DM.
No meu caso, por exemplo, o dataset de convênios é usado em muitos forms, quase tudo no sistema lida com os dados de convênios, com isso eu teria uma infinidade de datasources ´dsConv´ espalhandos nos forms da aplicação. Se tenho instâncias do DM independentes para cada form, então porque não deixar apenas um único dsConv lá no DM e usar ele para as conexões com os componentes de cada form? Não é muito mais racional?
Com relação ao ClientDataSet, realmente eu nunca usei esse componente, está lá no MIDAS certo? Vou estulá-lo melhor para entender suas diferenças.
Este tópico aqui, pelo menos pra mim, foi bastante esclarecedor, espero que tenha sido para outras pessoas também. Assim que eu tiver uma posição mais clara sobre usar IBDataSet ou ClientDataSet, posto aqui neste tópico.
Um abraço,
Com relação aos DataSources, já li pessoas dizerem que é apenas uma questão de preferência e organização, muitos fazem como vc diz, porém muitos dizem ser errado, pois mistura coisas que deveriam estar em outro local, na prática, não muda nada. Prefiro manter as coisas mais organizadas deixando os datasources ao lado dos datasets, se eu precisar de algo um pouco diferente, aí sim coloco um datasource no form e trabalho com ele separado, mas como agora terei DMs proprios para cada form, faço com eles o que for necessário em cada instanciamento, mas mantenho os datasources no DM.
No meu caso, por exemplo, o dataset de convênios é usado em muitos forms, quase tudo no sistema lida com os dados de convênios, com isso eu teria uma infinidade de datasources ´dsConv´ espalhandos nos forms da aplicação. Se tenho instâncias do DM independentes para cada form, então porque não deixar apenas um único dsConv lá no DM e usar ele para as conexões com os componentes de cada form? Não é muito mais racional?
Com relação ao ClientDataSet, realmente eu nunca usei esse componente, está lá no MIDAS certo? Vou estulá-lo melhor para entender suas diferenças.
Este tópico aqui, pelo menos pra mim, foi bastante esclarecedor, espero que tenha sido para outras pessoas também. Assim que eu tiver uma posição mais clara sobre usar IBDataSet ou ClientDataSet, posto aqui neste tópico.
Um abraço,
GOSTEI 0
Bon Jovi
26/10/2005
[size=9:54a4384420][i:54a4384420]´No meu caso, por exemplo, o dataset de convênios é usado em muitos forms, quase tudo no sistema lida com os dados de convênios, com isso eu teria uma infinidade de datasources ´dsConv´ espalhandos nos forms da aplicação. Se tenho instâncias do DM independentes para cada form, então porque não deixar apenas um único dsConv lá no DM e usar ele para as conexões com os componentes de cada form? Não é muito mais racional´[/i:54a4384420][/size:54a4384420]
Sim, pode ser, tudo depende do caso mesmo.
[size=9:54a4384420][i:54a4384420]
´Assim que eu tiver uma posição mais clara sobre usar IBDataSet ou ClientDataSet, posto aqui neste tópico. ´[/i:54a4384420][/size:54a4384420]
Ok. Sobre Midas a questão não é usar IBDataSet ou ClientDataSet, e sim os dois ao mesmo tempo, o IBDataSet serveria apenas pra trazer os dados do servidor e manter na memória do ClientDataSet. Se está começando o projeto agora, vale a pena partir logo pra esse lado.
Sim, pode ser, tudo depende do caso mesmo.
[size=9:54a4384420][i:54a4384420]
´Assim que eu tiver uma posição mais clara sobre usar IBDataSet ou ClientDataSet, posto aqui neste tópico. ´[/i:54a4384420][/size:54a4384420]
Ok. Sobre Midas a questão não é usar IBDataSet ou ClientDataSet, e sim os dois ao mesmo tempo, o IBDataSet serveria apenas pra trazer os dados do servidor e manter na memória do ClientDataSet. Se está começando o projeto agora, vale a pena partir logo pra esse lado.
GOSTEI 0
Aerreira
26/10/2005
É... acabei tendo que ceder... vou ter que colocar os DataSources todos nos forms mesmo, pois somente em run-time eu tenho o dmLocal ativo e pronto para ser relacionado aos componentes do form, em design-time não tenho como relacionar os componentes do form a um datasource dentro de um DataModule que ainda não existe.
Daria certo se, via código, eu fizesse a ligação da propriedade datasource de todos os componentes de cada form ao dmLocal, mas isso seria coisa de maluco... Daria muito trabalho. Vou ter então que colocar os datasources no form para poder ligar os componentes neles, e ao instanciar o dmLocal eu apenas faço a ligação entre o datasouce ao dataset recem instanciado...
É isso.
Daria certo se, via código, eu fizesse a ligação da propriedade datasource de todos os componentes de cada form ao dmLocal, mas isso seria coisa de maluco... Daria muito trabalho. Vou ter então que colocar os datasources no form para poder ligar os componentes neles, e ao instanciar o dmLocal eu apenas faço a ligação entre o datasouce ao dataset recem instanciado...
É isso.
GOSTEI 0
João
26/10/2005
Eu costumo criar uma cópia do datamodule para cada form.
Para fazer isto faça o seguinte:
No uses da sua unit declare o unit do datamodule;
Na seção private declare uma variável que receberá a cópia do datamodule: DMLocal : TDataModule;
No on create do seu form coloque:
DMLocal := TDataModule.Create(Self)
DataSource1.DataSet := DMLocal.NomeTabela;
Para fazer isto faça o seguinte:
No uses da sua unit declare o unit do datamodule;
Na seção private declare uma variável que receberá a cópia do datamodule: DMLocal : TDataModule;
No on create do seu form coloque:
DMLocal := TDataModule.Create(Self)
DataSource1.DataSet := DMLocal.NomeTabela;
No caso eu não tenho o dataSource posso usar o fdquery e outra é >>DMLocal : TDataModule; <<isso eu coloco no meu form né, e isso também >>
DMLocal := TDataModule.Create(Self)
DataSource1.DataSet := DMLocal.NomeTabela;<<
Então concluindo que não vai nada no datamodule?
GOSTEI 0