Форум: "Базы";
Текущий архив: 2004.12.26;
Скачать: [xml.tar.bz2];
ВнизУтечка памяти в TADODataset. Найти похожие ветки
← →
b@mboZe (2004-11-26 12:07) [0]Всем доброго времени суток.
У меня следующая задача: импортировать данные из excel файлов по списку (в списке >30 файлов) в MS SQL БД.
Возникла проблема: при занесении значений в TADODataset память, выделенная под них, не освобождается. Т.е. код типа
ADODataset.FieldValues["Field1"] := "String constant";
дает утечку памяти. Мне, конечно, не жалко одну строку, но проблема в том, таких строк в одном .xls от 3000-7000 умножить на количество файлов = весьма ощутимая утечка памяти.
Факт утечки проверял MemProof-ом. На нижеследующий пример Memproof в результатах (Resource Details) пишет
...
1265 SysString 0017BDFC 16 SysAllocStringLen(Liking string #5,16)
1271 SysString 0017BDFC 16 SysAllocStringLen(Liking string #6,16)
...
7193 SysString 0017BDFC 18 SysAllocStringLen(Liking string #993,18)
7199 SysString 0017BDFC 18 SysAllocStringLen(Liking string #994,18)
...
т.е. не была освобождена память на строки "Liking string #" c 1 по 1000. На закладке счетчиков ресурсов (Resource counters) он пишет:
Resources Resource Count Resource Size
Area Item Current # Peak # Current Size Peak Size
...
COM CoInitialize 0 1 0 0
OLE SysString 1002 1008 17918 18395
GDI Pen 0 1 0 0
...
Т.е. не освобождено 1002 строк, причем из OLE. Вопрос, по сути, относится скорее к COM ветке форума, однако, ИМХО, веротность найти ответ в этой ветке больше.
Может, кто-нибудь сталкивался с такой проблемой?
Вот пример кода, вызывающего утечку:
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
Conn: TADOConnection;
Comm: TADOCommand;
ds: TADODataSet;
begin
Conn := TADOConnection.Create(self);
Conn.ConnectionString := "Provider=SQLOLEDB.1;Password=;Persist"
+ " Security Info=true;User ID=bamboze;Initial Catalog=DebitCredit;Data "
+ "Source=PHYSALIS\BAMMSSQL;"
+ "Workstation ID=PHYSALIS;";
Conn.LoginPrompt := true;
conn.Connected := true;
Comm := TADOCommand.Create(self);
Comm.Connection := Conn;
Comm.CommandText := "if object_id(""T_TMP_TEST"") is not null drop table T_TMP_TEST create table T_TMP_TEST(id integer identity(1,1), Value varchar(255))";
Comm.Execute;
ds := TADODataSet.Create(self);
ds.Connection := conn;
ds.CommandType := cmdTable;
ds.CommandText := "T_TMP_TEST";
ds.Active := false;
ds.Active := true;
for i :=1 to 1000 do
begin
ds.Append;
ds.FieldByName("Value").Value := "Liking string #" + IntToStr(i);
end;
ds.Free;
comm.Free;
conn.Free;
ShowMessage("Done!");
end;
← →
Johnmen © (2004-11-26 13:03) [1]1. После второй строки тела цикла - ds.Post; (или 1 раз после цикла)
2. Перед разрушением соединения его надо разорвать.
← →
b@mboZe (2004-11-26 13:36) [2]Johnmen © (26.11.04 13:03) [1]
Спасибо за замечания, однако утечку это не устранило :( . OLE по-прежнему не освобождает память строк.
Кстати: пробовал использовать TADOCommand ("insert T_TMP_TEST ...") вместо TADODataset, т.е. в цикле
ADOCommand.CommandText := "insert TPriceExcelPreImport values(""Liking string #"+ IntToStr(i)+""")";
ADOCommand.Execute;
Тоже не освобождается память! Просто на этот раз пишет, что не освобождена память, выделенная под строки "insert TPriceExcelPreImport values("Liking string #1")" и т.п.
Мастера, неужели никто не сталкивался с подобной проблемой/задачей? Какие есть альтернативные способы импортировать из excel в MS SQL ? (кроме DTS - их можно создать только на 1 конкретный excel-файл; и последовательности сохранить xls как txt, импортировать используя bcp.exe)
← →
Johnmen © (2004-11-26 13:49) [3]>b@mboZe
Посмотри, будет ли утечка (нарастание количества утёкшего), если
запустить-выйти, запустить-выйти, ...
← →
b@mboZe © (2004-11-26 13:54) [4]Проверял, не будет. Утечка возникает только если запускать импорт.
← →
Johnmen © (2004-11-26 14:20) [5]Вот я и имел в виду - запустить импорт-выйти, запустить импорт-выйти, ...
← →
b@mboZe © (2004-11-26 14:57) [6]Три раза подряд запустил импорт, результат: около 3000 неосвообжденных строк. Т.е. ADO выделяет пямять, использует, и забывает освободить.
В самом ADO проблемы могут быть?
← →
Johnmen © (2004-11-26 15:18) [7]А от сервера автоматизации Exel отсоединяешься ? А подсоединяешься как ? Сервер выгружаешь ?
← →
b@mboZe © (2004-11-26 15:31) [8]Ранним связыванием. Вот так заканчиваю сессию с excel:
if Assigned(ExcelApp) then
begin
ExcelApp.Workbooks[1].Close(false, EmptyParam, EmptyParam, xlLCID);
ExcelApp.Workbooks.Close(xlLCID);
ExcelApp.Quit;
//FreeAndNil(Values);
FreeAndNil(ExcelApp);
end;
if Assigned(ExcelWorkSheet1) then
FreeAndNil(ExcelWorkSheet1);
Вот так начинаю сессию:
ExcelApp := TExcelApplication.Create(self);
ExcelWorksheet1 := TExcelWorksheet.Create(self);
Result := false;
ExcelApp.ConnectKind := ckNewInstance;
ExcelApp.Connect;
if Assigned(ExcelApp) then begin
ExcelApp.Visible[xlLCID] := false;
if ExcelApp.WindowState[xlLCID] = TOLEEnum(xlMinimized) then
ExcelApp.WindowState[xlLCID] := TOLEEnum(xlNormal);
ExcelApp.ScreenUpdating[xlLCID] := true;
end;
s:=filename;
ExcelApp.Workbooks.Open(s, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam, false, xlLCID);
ExcelWorksheet1.ConnectTo( ExcelApp.ActiveSheet as _Worksheet);
Values := ExcelWorksheet1.UsedRange[xlLCID].Value;
iPLFieldsCount := VarArrayHighBound(Values, 2);
далее Values[i,j] считываю в TADOTable или TADOCommand
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2004.12.26;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.045 c