copiar registros de clientdataset sem varrer
seguinte: tenho 2 clientdatasets e quero copiar os registros de um para o outro sem varrer. Só que um dos clients está filtrado, e eu quero copiar só os registros filtrados e não todos.
Se eu usar a propriedade data do tclientdataset eu copio todos os registros, mas eu não quero, quero copiar só os filtrados, para gerar um ´data´ menor.
Preciso disso porque esse data eu vou passar como parametro variant para um metodo de um remotedatamodule.
Tem algum jeito?
Se eu usar a propriedade data do tclientdataset eu copio todos os registros, mas eu não quero, quero copiar só os filtrados, para gerar um ´data´ menor.
Preciso disso porque esse data eu vou passar como parametro variant para um metodo de um remotedatamodule.
Tem algum jeito?
Vitor Rubio
Curtidas 0
Respostas
Emerson Nascimento
11/11/2008
só conheço fazendo a varredura nos registros.
se for o caso, desabilite os controles para ganhar em performance.
se for o caso, desabilite os controles para ganhar em performance.
cdsOriginal.DisableControls; [faz a varredura e a cópia] cdsOriginal.EnableControls;
GOSTEI 0
Vitor Rubio
11/11/2008
eu já fiz assim mesmo, mas se eu arranjasse outro jeito de fazer isso sem varrer ia ficar mais generico, mas seguro e talvez mais rapido.
coloquei os disablecontrols e enablecontrols, coloquei tambem register para essa procedure ser executada nos registradores, mas não sei se vou ter um ganho significativo de performance com isso.
valew!
coloquei os disablecontrols e enablecontrols, coloquei tambem register para essa procedure ser executada nos registradores, mas não sei se vou ter um ganho significativo de performance com isso.
valew!
GOSTEI 0
Diegotiemann
11/11/2008
tente o seguinte:
ClientDataSet1.data:=ClientDataSet2.Data;
GOSTEI 0
Vitor Rubio
11/11/2008
tente o seguinte:
ClientDataSet1.data:=ClientDataSet2.Data;
diego, desse jeito eu copio todos os dados, não só os filtrados.
Vou tentar usando clonecursor e copiar o data do dataset ´clonado´, se funcionar eu posto aqui.
GOSTEI 0
Vitor Rubio
11/11/2008
com clone cursor tambem não adianta, olha só: exemplo tipico de conexão ao banco de dados employee.gdb, com dbxpress.
2 dbgrids para ver o conteudo dos 2 datasets, etc.
nenhuma dessas opções colocou no segundo client só o ´EMP_NO=2´, ou seja: APARENTEMENTE É IMPOSSIVEL COPIAR O DATA FILTRADO, SEM TER DE VARRER.
Embora, se for varrer, dar um disablecontrols, usar um cursor clonado e varrer o clone seria uma boa opção para não tirar o clientdataset da ´posição´ que ele estiver.
2 dbgrids para ver o conteudo dos 2 datasets, etc.
ClientDataSet1.Filter := ´EMP_NO=2´; ClientDataSet1.Filtered := true; cds := TClientDataSet.Create(nil); //cds.CloneCursor(ClientDataSet1, false, false); //cds.CloneCursor(ClientDataSet1, false, true); //cds.CloneCursor(ClientDataSet1, true, false); cds.CloneCursor(ClientDataSet1, true, true); ClientDataSet2.Data := cds.Data; cds.Free;
nenhuma dessas opções colocou no segundo client só o ´EMP_NO=2´, ou seja: APARENTEMENTE É IMPOSSIVEL COPIAR O DATA FILTRADO, SEM TER DE VARRER.
Embora, se for varrer, dar um disablecontrols, usar um cursor clonado e varrer o clone seria uma boa opção para não tirar o clientdataset da ´posição´ que ele estiver.
GOSTEI 0
Tonidavi2004
11/11/2008
vitor^_^ você pode fazer assim.
type
TForm1 = class(TForm)
function DataSetProvider1DataRequest(Sender: TObject;
Input: OleVariant): OleVariant;
procedure Button1Click(Sender: TObject);
implementation
{$R *.DFM}
function TForm1.DataSetProvider1DataRequest(Sender: TObject;
Input: OleVariant): OleVariant;
begin
with (Sender as TDataSetProvider) do
begin
DataSet.Filter := Input;
DataSet.Filtered := True;
Result := Data;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientDataSet2.CreateDataSet;
ClientDataSet2.Data := ClientDataSet1.DataRequest(Seu Filtro);
end;
GOSTEI 0
Upgradesource
11/11/2008
Vitor
não sei o que vc quer fazer ou se tem que ser assim, tentei achar algo forma de fazer isso com o filter, mas sem sucesso.
Mas se for possivel tente usar o param
ex
no botao filtrar tente algo asism
clientdataset1.close;
ClientDataSet1.Params[0].AsInteger := 19;
clientdataset1.Open;
ClientDataSet1.SaveToFile(´tabela.cds´);
ClientDataSet2.LoadFromFile(´tabela.cds´);
clientdataset2.open;
[ ]´s
não sei o que vc quer fazer ou se tem que ser assim, tentei achar algo forma de fazer isso com o filter, mas sem sucesso.
Mas se for possivel tente usar o param
ex
no botao filtrar tente algo asism
clientdataset1.close;
ClientDataSet1.Params[0].AsInteger := 19;
clientdataset1.Open;
ClientDataSet1.SaveToFile(´tabela.cds´);
ClientDataSet2.LoadFromFile(´tabela.cds´);
clientdataset2.open;
[ ]´s
GOSTEI 0
Vitor Rubio
11/11/2008
não entendi essa dica do params, meu cds não tem parametros.
vou experimentar a dica do tonidavi2004, se der certo eu posto aqui
vou experimentar a dica do tonidavi2004, se der certo eu posto aqui
GOSTEI 0
Luiz Henrique
11/11/2008
Blz vitor,
Set a opcao ClientDataSet1.LogChanges:= False, para nao efetuar backups de registros e logs, segundo um colega de outro forum NDDV, economiza memoria, + velocidade e etc...
T+
Set a opcao ClientDataSet1.LogChanges:= False, para nao efetuar backups de registros e logs, segundo um colega de outro forum NDDV, economiza memoria, + velocidade e etc...
T+
GOSTEI 0
Vitor Rubio
11/11/2008
usando o datarequest dá exception de operation not alowed with unidirectional datasets.
isso porque o meu dataset é um sql dataset do dbxpress.
talvez se ligar em outro provider e outro client funcione.
isso porque o meu dataset é um sql dataset do dbxpress.
talvez se ligar em outro provider e outro client funcione.
GOSTEI 0
Tonidavi2004
11/11/2008
Post aqui o código que fez que causou o erro.
GOSTEI 0
Vitor Rubio
11/11/2008
FuncionoooooooooU!!!
porem eu preciso de mais um provider e mais um dataset, e encadear tudo, mas funcionou.
porem eu preciso de mais um provider e mais um dataset, e encadear tudo, mas funcionou.
GOSTEI 0
Vitor Rubio
11/11/2008
o codigo do tonidavi2004 funcionou, mas eu tive que ligar outro client e provider, pois não funcion com datasets unidirecionais, e o dataset do meu provider era um sqldataset.
vou postar o codigo do dfm para que vocês possam copiar - colar, e o codigo da unit
unit:
dfm:
o codigo que deu erro é o mesmo do button2, ou seja, a dica do tonidavi2004, só que quando deu erro eu tentei copiar o clientdataset 1 filtrado para o cds3
vou testar essa ultima dica para ver se da certo
vou postar o codigo do dfm para que vocês possam copiar - colar, e o codigo da unit
unit:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, DBXpress, FMTBcd, DB, StdCtrls, Provider, DBClient, Grids,
DBGrids, SqlExpr;
type
TForm1 = class(TForm)
SQLConnection1: TSQLConnection;
SQLDataSet1: TSQLDataSet;
DBGrid1: TDBGrid;
ClientDataSet1: TClientDataSet;
DataSetProvider1: TDataSetProvider;
Button3: TButton;
ClientDataSet2: TClientDataSet;
DataSource1: TDataSource;
DataSource2: TDataSource;
DBGrid2: TDBGrid;
Button2: TButton;
DataSetProvider2: TDataSetProvider;
ClientDataSet3: TClientDataSet;
procedure Button3Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
function DataSetProvider2DataRequest(Sender: TObject;
Input: OleVariant): OleVariant;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button3Click(Sender: TObject);
var cds: TClientDataSet;
begin
ClientDataSet2.Filter := ´EMP_NO=2´;
ClientDataSet2.Filtered := true;
cds := TClientDataSet.Create(nil);
//cds.CloneCursor(ClientDataSet2, false, false);
//cds.CloneCursor(ClientDataSet2, false, true);
//cds.CloneCursor(ClientDataSet2, true, false);
cds.CloneCursor(ClientDataSet2, true, true);
ClientDataSet3.Data := cds.Data;
cds.Free;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
ClientDataSet3.Data := ClientDataSet2.DataRequest(´EMP_NO=2´);
end;
function TForm1.DataSetProvider2DataRequest(Sender: TObject;
Input: OleVariant): OleVariant;
begin
with (Sender as TDataSetProvider) do
begin
DataSet.Filter := Input;
DataSet.Filtered := True;
Result := Data;
end;
end;
end.dfm:
object Form1: TForm1 Left = 290 Top = 278 Width = 684 Height = 222 Caption = ´Form1´ Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = ´MS Sans Serif´ Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object DBGrid1: TDBGrid Left = 16 Top = 16 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 Button3: TButton Left = 24 Top = 160 Width = 75 Height = 25 Caption = ´Button3´ TabOrder = 1 OnClick = Button3Click end object DBGrid2: TDBGrid Left = 344 Top = 16 Width = 320 Height = 120 DataSource = DataSource2 TabOrder = 2 TitleFont.Charset = DEFAULT_CHARSET TitleFont.Color = clWindowText TitleFont.Height = -11 TitleFont.Name = ´MS Sans Serif´ TitleFont.Style = [] end object Button2: TButton Left = 104 Top = 160 Width = 75 Height = 25 Caption = ´Button2´ TabOrder = 3 OnClick = Button2Click end object SQLConnection1: TSQLConnection ConnectionName = ´Employee.gdb´ DriverName = ´Interbase´ GetDriverFunc = ´getSQLDriverINTERBASE´ LibraryName = ´dbexpint.dll´ LoginPrompt = False Params.Strings = ( ´DriverName=Interbase´ ´Database=C:\Arquivos de programas\Arquivos comuns\Borland Shared´ + ´\Data\employee.gdb´ ´RoleName=RoleName´ ´User_Name=sysdba´ ´Password=masterkey´ ´ServerCharSet=´ ´SQLDialect=3´ ´BlobSize=-1´ ´CommitRetain=False´ ´WaitOnLocks=True´ ´ErrorResourceFile=´ ´LocaleCode=0000´ ´Interbase TransIsolation=ReadCommited´ ´Trim Char=False´) VendorLib = ´gds32.dll´ Connected = True Left = 24 Top = 32 end object SQLDataSet1: TSQLDataSet CommandText = ´select * from EMPLOYEE´ MaxBlobSize = -1 Params = <> SQLConnection = SQLConnection1 Left = 64 Top = 32 end object ClientDataSet1: TClientDataSet Aggregates = <> Params = <> ProviderName = ´DataSetProvider1´ Left = 136 Top = 32 end object DataSetProvider1: TDataSetProvider DataSet = SQLDataSet1 Left = 96 Top = 32 end object ClientDataSet2: TClientDataSet Active = True Aggregates = <> Params = <> ProviderName = ´DataSetProvider2´ Left = 208 Top = 32 end object DataSource1: TDataSource DataSet = ClientDataSet2 Left = 136 Top = 80 end object DataSource2: TDataSource DataSet = ClientDataSet3 Left = 384 Top = 56 end object DataSetProvider2: TDataSetProvider DataSet = ClientDataSet1 OnDataRequest = DataSetProvider2DataRequest Left = 176 Top = 32 end object ClientDataSet3: TClientDataSet Aggregates = <> Params = <> Left = 424 Top = 24 end end
o codigo que deu erro é o mesmo do button2, ou seja, a dica do tonidavi2004, só que quando deu erro eu tentei copiar o clientdataset 1 filtrado para o cds3
vou testar essa ultima dica para ver se da certo
GOSTEI 0
Vitor Rubio
11/11/2008
mesmo com o logchanges false ele copia todo o data, se eu tentar copiar o data direto depois de filtrado.
Tirando a varredura, o datarequest do tonidavi2004 foi o jeito que funcionou.
Agora me pergunto o que seria mais performatico: a dica do datarequest ou a varredura?
Tirando a varredura, o datarequest do tonidavi2004 foi o jeito que funcionou.
Agora me pergunto o que seria mais performatico: a dica do datarequest ou a varredura?
GOSTEI 0
Discorpio
11/11/2008
Boa noite a todos.
Existe um outro jeito, Vitor, e esse jeito chama-se IBExpert.
Como ?
O IBExpert permite você gerar Scripting de SQL com os dados da tabela, por exemplo, se a sua tabela contiver 10.000 registros, ele gera 10.000 instruções Inserts.
Ao abrir o IBExpert, você abre o banco e a tabela que voce quer clonar, no canto superior esquerdo da janela da tabela, tem um botão chamado table, a clicar ali voce seleciona Export Data into Script, então voce pode selecionar os campos que queira exportar na aba Fields e na combo Export as, voce escolhe a sentença, se Insert Stataments, Update Statements, ou Procedure Statements, em File Name, digite o nome do arquivo texto que ele vai exportar a sentença.
Se voce preferir com os dados filtrados, aplique o filtro indo na aba Data e do mesmo lado esquerdo, aplique o Filtro Criteria e depois Apply Filter.
Isto é bom até quando quero transportar dados de um tipo de banco de dados para outro tipo, Ex: FireBird para PostGres
Esta é uma opção caso voce não queira fazer isto via código.
Existe um outro jeito, Vitor, e esse jeito chama-se IBExpert.
Como ?
O IBExpert permite você gerar Scripting de SQL com os dados da tabela, por exemplo, se a sua tabela contiver 10.000 registros, ele gera 10.000 instruções Inserts.
Ao abrir o IBExpert, você abre o banco e a tabela que voce quer clonar, no canto superior esquerdo da janela da tabela, tem um botão chamado table, a clicar ali voce seleciona Export Data into Script, então voce pode selecionar os campos que queira exportar na aba Fields e na combo Export as, voce escolhe a sentença, se Insert Stataments, Update Statements, ou Procedure Statements, em File Name, digite o nome do arquivo texto que ele vai exportar a sentença.
Se voce preferir com os dados filtrados, aplique o filtro indo na aba Data e do mesmo lado esquerdo, aplique o Filtro Criteria e depois Apply Filter.
Isto é bom até quando quero transportar dados de um tipo de banco de dados para outro tipo, Ex: FireBird para PostGres
Esta é uma opção caso voce não queira fazer isto via código.
GOSTEI 0
Vitor Rubio
11/11/2008
Olá Jorge, obrigado pela dica. Eu já conhecia o IBExpert, uso ele há 4 anos. Já usei muito esse recurso para transporte ou migração de dados.
Acho que você não entendeu direito a questão, mas eu já encontrei a solução:
Fica aí como uma dica para você: você pode usar um clientdataset já com dados como um provider!
Abaixo eu explico qual era minha real necessidade.
O que eu precisava era copiar dados de um clientdataset para outro, mas sem varrer o client. Não é que eu queira gravar os registros em outra tabela ou outro banco. Eu tentava na verdade fechar o client original para me desconectar do banco e trabalhar com um client em memoria. (não precisaria me preocupar com updates porque era só filtro e consulta).
Só que a propriedade data do clientdataset, que é um olevariant, quando você copia de um client para outro vão todos os dados, o conjunto inteiro, mesmo o clientdataset original estando filtrado.
Não sei se você já trabalhou com ntier, mas com ntier você não pode passar objetos do client para o server(ou vice-versa), só variaveis primitivas e olevariant. Então passar um clientdataset filtrado está fora de cogitação. Então ao executar metodos do server eu devo passar parametros (ou receber) olevariant.
então quis passar do meu servidor para a aplicação um olevariant com o data filtrado, e do outro lado eu criava um clientdataset e atribuia o data a ele. (o data já cria os cmpos e tudo o que eu preciso).
Porem.... como passar o data já filtrado, ou seja, só com os registros que eu quero usar e não tudo ?(ajuda a diminuir o trafego na rede).
Já achei a solução. Recebi essa dica no grupo NDDV, e recomendo a todos.
[url]http://br.groups.yahoo.com/group/NDDV/message/10095[/url]
Acho que você não entendeu direito a questão, mas eu já encontrei a solução:
ta... entao tente fazer isso ... ClientDataSet1 = FILTRADO ( na aplicacao cliente ) ClientDataSet2 ... sera criado em tempo de execucao... e um terceiro so pra mostrar em uma grid para ver se esta transendo so o DATA filtrado ... este deve estar ´´colado´´, var ClientDataSet2 : TClientDataSet ; Data2 :OleVariant ; begin ClientDataSet2 := TClientDataSet.Create ( nil ) ; ClientDataSet2.SetProvider ( ClienteDataSet1 ) ; ClientDataSet2.Open ; Data2 := ClientDataSet2.Data ; ClientDataSet2.Close ; ClientDataSet3.Data = Data2 ; end ;
Fica aí como uma dica para você: você pode usar um clientdataset já com dados como um provider!
Abaixo eu explico qual era minha real necessidade.
O que eu precisava era copiar dados de um clientdataset para outro, mas sem varrer o client. Não é que eu queira gravar os registros em outra tabela ou outro banco. Eu tentava na verdade fechar o client original para me desconectar do banco e trabalhar com um client em memoria. (não precisaria me preocupar com updates porque era só filtro e consulta).
Só que a propriedade data do clientdataset, que é um olevariant, quando você copia de um client para outro vão todos os dados, o conjunto inteiro, mesmo o clientdataset original estando filtrado.
Não sei se você já trabalhou com ntier, mas com ntier você não pode passar objetos do client para o server(ou vice-versa), só variaveis primitivas e olevariant. Então passar um clientdataset filtrado está fora de cogitação. Então ao executar metodos do server eu devo passar parametros (ou receber) olevariant.
então quis passar do meu servidor para a aplicação um olevariant com o data filtrado, e do outro lado eu criava um clientdataset e atribuia o data a ele. (o data já cria os cmpos e tudo o que eu preciso).
Porem.... como passar o data já filtrado, ou seja, só com os registros que eu quero usar e não tudo ?(ajuda a diminuir o trafego na rede).
Já achei a solução. Recebi essa dica no grupo NDDV, e recomendo a todos.
[url]http://br.groups.yahoo.com/group/NDDV/message/10095[/url]
GOSTEI 0