-
Подскажите, как можно передать полученный recordset (ADO) в одной программе в другую через TCP Нужно что-то типа (конечно такая конструкция не работает - rs - это указатель на recordset): var ms: TMemoryStream; rs: _Recordset; begin ms.Write(rs,SizeOf(rs)); TcpClient1.SendStream(ms); end;
Одна программа получает данные с SQL Server и раздаёт их другим клиентам по tcp (). Может есть другой способ получения результата выполнения SQL-запроса, который позволит это сделать?
-
> Нужно что-то типа (конечно такая конструкция не работает - rs - это указатель на recordset): естественно, указатель с одной машины на другой ничего не значит. копируй данные. есть возможность загнать их в ADOStream, а после передачи загрузить из него.
> Может есть другой способ получения результата выполнения SQL-запроса, который позволит это сделать? трехзвенка, midas, soap, ...
-
если можно, то покажите на примере нашёл один пример, но там идёт преобразование через XML, а это будет достаточно долго (есть правда через ADTG (Advanced Data Tablegram), но как его дальше использовать не понимаю): var adoStream: OleVariant; St: TStrings; begin // Сначала ADODB.RecordSet -> ADODB.Stream через XML adoStream := CreateOLEObject('ADODB.Stream'); Variant(ARecordSet).Save(adoStream, adPersistXML); // Теперь XML -> TStrings St := TStringList.Create; St.Text := adoStream.ReadText(adoStream.Size); // Ну а теперь всё просто AddFromStrings(AName, St); // Чищу память St.Free; adoStream := UnAssigned;
Изначально я думал, что можно сделать так: у _RecordSet есть метод Save(FileName: WideString, PersistFormat: TOleEnum) сохранить данные в файл (только не на диске, а в памяти) и записать двоичные данные в TMemoryStream (поток сначало содержит структуру, где указывается тип данных следуемых далее в потоке) и всё это передать одним потоком по tcp. Но с реализацией ничего пока не получилось, вообще это возможно?
Нужно что-бы работало по возможности быстро.
-
а это будет достаточно долго
"достаточно долго" - это когда сохранение данных рекордсета занимает больше времени, чем последущая передача этих данных по сети
так что на самом деле все наоборот - это "все достаточно быстро"
-
> записать двоичные данные в TMemoryStream procedure SendDataset(Content: TStream; DataSet: TADODataSet);
var
adoStream: OleVariant;
Buffer: Variant;
PBuffer: pointer;
size: integer;
begin
adoStream:= CreateOLEObject('ADODB.Stream');
try
Variant(DataSet.Recordset).Save(adoStream, adPersistADTG);
size:= adoStream.Size;
Buffer := adoStream.Read(size);
PBuffer:= VarArrayLock(Buffer);
try
Content.WriteBuffer(PBuffer^, size);
finally
VarArrayUnlock(Buffer);
end;
finally
adoStream:= UnAssigned;
end;
end;
-
Спасибо, будем пробовать
-
Дополнительно вопрос: в Buffer будет данные в формате который определяет ADO? а если результат SQL-запроса получать в Linux (например, с PostgreSQL) и передавать его по сети, то формат данных в переменной Buffer (в потоке) будет другим? Здесь наверно лучше использовать преобразование результат SQL-запроса в XML? Существуют стандарты на единый формат данных результата SQL-запроса?
имеется ввиду, что программа получения данных с SQL Server (PostgreSQL) будет написана под Linux, а не доступ к SQL Server (linux) из Windows через ODBC.
Спасибо.
-
> трехзвенка, midas, soap
> dm37 (21.07.10 14:12) [2] > > если можно, то покажите на примере
Этой теме посвящено больше двух трети толстенной книги "Руководство для разработчика" от указанной D7.
-
to sniknik если не затруднит, то можно ещё пример обратного преобразования TStream -> Recordset
Спасибо за помощь
-
В итоге получилось это. Укажите пожалуйста на возможные ошибки (но пока работает): procedure AddRecordsetToStream(stream: TStream; const Recordset: _Recordset); var rs: Variant; begin if(Recordset = nil) then Exit; try rs:=CreateOleObject('ADODB.Recordset'); rs:=Recordset; rs.Save(TStreamAdapter.Create(stream) as IUnknown, adPersistADTG); finally end; end;
function RecordsetFromStream(const stream: TStream; pos: int64; size: int64): _Recordset; var rs: Variant; temp: TStream; begin Result := nil; // stream.Position:=pos; temp:=TMemoryStream.Create; temp.CopyFrom(stream,size); try temp.Position:=0; rs:=CreateOleObject('ADODB.Recordset'); rs.Open(TStreamAdapter.Create(temp) as IUnknown); Result:=IUnknown(rs) as _Recordset; finally temp.Free; end; end;
-
dm37 (22.07.10 14:46) [9] TStreamAdapter.Create(stream) as IUnknownточно не помню - он точно самоуничтожится? так надежней procedure AddRecordsetToStream(stream: TStream; Recordset: _Recordset);
var
st:TStreamAdapter;
rs:variant;
begin
if(Recordset = nil) then Exit;
st:=TStreamAdapter.Create(stream);
try
rs:=Recordset as IDispatch;
rs.Save(st as IUnknown, adPersistADTG);
finally
st.Free;
end;
end;
|