![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как правильно отвязать TADODataSet от сервера? [D7, MSSQL]
Zelius © (2004-03-29 17:47:00)Есть многопоточное серверное приложение, которое постоянно запрашивает базу данных. Мысль была такая, выполнить запрос, отвязать его от базы и отдать его в другой поток на обработку, а текущий поток пусть выполняет следующий запрос. Как я это делаю:
ReadUserDataASP.Open;
UnbindedDS := TADODataSet.Create(nil);
UnbindedDS.Clone(ReadUserDataASP);
UnbindedDS.Connection := nil;
дальше я этот UnbindedDS передаю в другой поток. Все работало, но тут стало вылезать сообщение "Could not continue scan with nolock due to data movement". Я так понимаю, что раз эта ошибка вылезает, то значит моя затея с отвязывание не удалась. Прошу совета, как правильно отвязываться наборы данных. Спасибо.
Zelius (2004-03-31 11:43:00) [1]
> Delirium © (30.03.04 18:37) [25]
попробую... спасибо!
Delirium (2004-03-30 18:37:00) [2]К слову чтобы "оторвать" _Recordset от сервера, вовсе нет необходимости оборачивать его TADODataSet, достаточно вызвать соответствующий метод (
Rs[0].Set_ActiveConnection(nil);).
Delirium (2004-03-30 18:13:00) [3]"когда я закрою основную хр.проц., то остальные будут ссылаться на закрытые же данные" - тут не всё так просто, когда ты уничтожаешь ADODataSet, ты вовсе не уничтожаешь _RecordSet - он, как честный COM, живёт до тех пор пока на него есть ссылки, коими и являются элемены массива из моего примера. Их элементарно можно перемещать между потоками, т.к. это позволяет COM-архитектура ADO.
Zelius (2004-03-30 17:58:00) [4]
> Delirium © (30.03.04 17:29) [21]
просто я считал, что когда я закрою основную хр.проц., то остальные будут ссылаться на закрытые же данные.
Zelius (2004-03-30 17:52:00) [5]
> jocko ©
хмм... а при чем тут ltBatchOptimistic? Я вообще ничего не меняю...
Delirium (2004-03-30 17:29:00) [6]"это второй, а первый датасет?" - а самому подумать?
procedure TForm1.Button1Click(Sender: TObject);
var R:_RecordSet;
v:OleVariant;
i:integer;
Rs:array of _RecordSet;
begin
SetLength(Rs, 1);
Rs[0]:=ADOQuery1.Recordset;
while true do
begin
R:=ADOQuery1.Recordset.NextRecordset(v);
if R<>nil then
begin
i:=Length(Rs);
SetLength(Rs, i+1);
Rs[i]:=R;
end
else break;
end;
end;
Zelius (2004-03-30 17:08:00) [7]
> jocko © (30.03.04 16:53) [17]
ок, посмотрю что такое ltBatchOptimistic...
Zelius (2004-03-30 17:08:00) [8]
> Delirium © (30.03.04 16:58) [18]
это второй, а первый датасет?
Delirium (2004-03-30 16:58:00) [9]"как их отдать так, что они не были привязаны к базе?"
...
UnbindedDS := TADODataSet.Create(nil);
UnbindedDS.Recordset:=ReadUserDataASP.Recordset.NextRecordset(v);
UnbindedDS.Connection := nil;
...
где тут необходим Clone ?
jocko (2004-03-30 16:53:00) [10]>15
NextRecordset + ltBatchOptimistic
Zelius (2004-03-30 16:39:00) [11]
> jocko ©
мне надо из данных построить xml страницу и отдать юзеру.
Zelius (2004-03-30 16:38:00) [12]А как? Есть проц. которая возвращает два набора, как их отдать так, что они не были привязаны к базе?
Delirium (2004-03-30 15:54:00) [13]Да "отвязывать" то элементарно, а вот клонировать зачем?
jocko (2004-03-30 15:39:00) [14]вообще не понятно "отвязать его от базы и отдать его в другой поток на обработку" предполагается что приложение само обрабатыват данные и при том в клиенте ?...
В этом случае проще написать хранимые процедуры и обрабатывать данные на сервере.
PS А если "отвязывать" набор данных, то чем плох ltBatchOptimistic?
Delirium (2004-03-30 15:39:00) [15]В общем я так и не понял для чего ты тут используешь Clone, ну и ладно 8-/
Zelius (2004-03-30 15:17:00) [16]А если после всех этих манипуляций вызывается ReadUserDataASP.Close, и после этого отдаются рекрдсеты, то ведь получается же отвязанный набор данных? Если подумать, то это даже хорошо, что бы не было лишнего дублирования.
Delirium (2004-03-30 14:57:00) [17]Но Clone - не копируетданные, он создаёт курсор к тем-же данным, т.е. новый элемент управления и всё.
Zelius (2004-03-30 14:23:00) [18]смысл в том, что бы разбить выборку данных и обработку на две части, проц. ReadUserDataASP возвращает два набора данных, потом я делаю
ReadUserDataASP.RecordSet := ReadUserDataASP.NextRecordset(i);
и повторяю процедуру с клонированием. после этого данные передаются на обработку в другой поток, а текущий выполняет след. запрос.
Delirium (2004-03-30 13:59:00) [19]Собственно при операции ReadUserDataASP.Connection := nil;
ReadUserDataASP то-же будет доступен, ни куда не денется, я не понимаю зачем тебе Clone ?
Zelius (2004-03-30 13:44:00) [20]
> Delirium ©
имел ввиду ADOStream
сейчас сделал так
ReadUserDataASP.Open;
UnbindedDS := TADODataSet.Create(nil);
UnbindedDS.Connection := AdoConnection;
UnbindedDS.Clone(ReadUserDataASP);
UnbindedDS.Connection := nil;
посмотрел дебагером - код отрабатывается и рекордсет доступен даже после удалени коннекшена. посмотрим, как будет работать...