EDBClient - Insufficiente memory for this operation
Pessoal, estou com um projetinho de teste aqui onde uma das tarefas é resolver um problema de memória que ocorre com armazenamento de arquivos utilizando ClientDataSet.
O objetivo é armazenar 100 (ou mais) arquivos PDF que possuem em média 47MB cada um. Cada arquivo será um registro do ClientDataSet.
Com o código acima, lá pela metade do processo estoura o erro "EDBClient - Insufficiente memory for this operation".
Já revirei a internet toda e não achei uma solução. =/
O objetivo é armazenar 100 (ou mais) arquivos PDF que possuem em média 47MB cada um. Cada arquivo será um registro do ClientDataSet.
for i := 1 to 100 do
begin
cds.Append;
TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo);
cds.Post;
end;
Com o código acima, lá pela metade do processo estoura o erro "EDBClient - Insufficiente memory for this operation".
Já revirei a internet toda e não achei uma solução. =/
Prophet
Curtidas 0
Respostas
Emerson Nascimento
23/09/2021
// coloque uma instrução que leia a tabela porem não retorne registros.
// por exemplo: tua tabela tem um campo ID que inicia em 1.
// coloque a seguinte instrução no ClientDataset:
// "SELECT * FROM TABELA WHERE ID = -1" sabendo que nenhum registro atenderá à condição
// ou seja, sempre que o ClientDataset for aberto, ele não trará registros
// daí você faz a iteração sempre fechando e abrindo o ClientDataset, de
// modo que tenha apenas 1 registro na memória, evitando o estouro.
for i := 1 to 100 do
begin
if cds.Active then cds.Close; // fecha o dataset (e libera memória)
cds.Open; // abre o dataset sem registros, visto que a instrução SQL está preparada para isto
cds.Append; // insere um registro na posição do ponteiro
TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo); // atribui o arquivo ao campo
cds.Post; // grava o conteúdo do dataset
cds.ApplyUpdates(0); // descarrega o conteúdo no banco de dados
end;GOSTEI 0
Prophet
23/09/2021
// coloque uma instrução que leia a tabela porem não retorne registros.
// por exemplo: tua tabela tem um campo ID que inicia em 1.
// coloque a seguinte instrução no ClientDataset:
// "SELECT * FROM TABELA WHERE ID = -1" sabendo que nenhum registro atenderá à condição
// ou seja, sempre que o ClientDataset for aberto, ele não trará registros
// daí você faz a iteração sempre fechando e abrindo o ClientDataset, de
// modo que tenha apenas 1 registro na memória, evitando o estouro.
for i := 1 to 100 do
begin
if cds.Active then cds.Close; // fecha o dataset (e libera memória)
cds.Open; // abre o dataset sem registros, visto que a instrução SQL está preparada para isto
cds.Append; // insere um registro na posição do ponteiro
TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo); // atribui o arquivo ao campo
cds.Post; // grava o conteúdo do dataset
cds.ApplyUpdates(0); // descarrega o conteúdo no banco de dados
end;Obrigado pela resposta, mas não resolveu =/
O problema é que não estou trabalhando com banco de dados. O objetivo do ClientDataSet é só armazenar os arquivos em memória (no caso, 100 arquivos) e depois é chamado um método que vai iterar sobre esse ClientDataSet e salvar cada arquivo num diretório específico.
Ele nem chega a entrar no método de salvar porque no meio do processo de alimentar o ClientDataSet dá o estouro de memória.
GOSTEI 0
Emerson Nascimento
23/09/2021
a lógica deveria ser a mesma.
você precisa esperar dar carga em 100 arquivos?
porque não pode fazer a gravação a cada leitura?
você precisa esperar dar carga em 100 arquivos?
porque não pode fazer a gravação a cada leitura?
for i := 1 to 100 do
begin
if cds.Active then cds.Close; // fecha o dataset (e libera memória)
cds.CreateDataset;
cds.Insert; // insere um novo registro
TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo); // atribui o arquivo ao campo
cds.Post; // grava o conteúdo do dataset
// grava o arquivo na pasta desejada
[...]
end;GOSTEI 0
Prophet
23/09/2021
a lógica deveria ser a mesma.
você precisa esperar dar carga em 100 arquivos?
porque não pode fazer a gravação a cada leitura?
você precisa esperar dar carga em 100 arquivos?
porque não pode fazer a gravação a cada leitura?
for i := 1 to 100 do
begin
if cds.Active then cds.Close; // fecha o dataset (e libera memória)
cds.CreateDataset;
cds.Insert; // insere um novo registro
TBlobField(cds.FieldByName('arquivo')).LoadFromFile(sCaminhoDoArquivo); // atribui o arquivo ao campo
cds.Post; // grava o conteúdo do dataset
// grava o arquivo na pasta desejada
[...]
end;Sim, entendo que existem N formas de fazer isso. Só que se eu tivesse que manter essa estrutura de primeiro carregar os 100 arquivos no ClientDataSet e só depois salvá-los num diretório, você enxerga alguma solução para evitar esse estouro de memória?
GOSTEI 0