Binh Ly 與 Deborah Pate 分別提供兩種傳遞 RecordSet 的方法:

一. Binh Ly 提供的方法

Something like this should work:

In Server:

func TFoo.GetRS: OleVariant;
var
  rs: _Recordset;
begin
  rs := CoRecordset.Create;
  rs.CursorLocation := adUseClient;
  rs.Open (..., adLockBatchOptimistic { if you want modifiable rs }, ... );
  rs._Set_ActiveConnection (nil);
  Result := rs;
end;

In Client:

var
  Foo: IFoo;
  rs: _Recordset;
begin
  Foo := CoFoo.Create;
  rs := IUnknown (Foo.GetRS) as _Recordset;
end;

have fun
--
Binh Ly
http://www.techvanguards.com


二. Deborah Pate 提供的方法


<>

Well, that's an easy way, when the components are overkill. 
If you use the New...|ActiveX wizards to create an ActiveX 
library and then create an automation object, you can 
easily add a method or a property of _Recordset type. Just 
select the library - the first line in the left hand window 
pane - in the Type Library Editor, and on the right you'll 
see a Uses tab. Select it, then right-click in that window 
and select Show all libraries. Now make sure that 
"Microsoft ActiveX Data Objects Recordset 2.5" is checked, 
and you'll be able to specify _recordset interfaces for 
your own interfaces' properties and method parameters. 

For example, I just created an automation object, and added 
a Recordset property to it using the Type Library Editor, 
so that the interface looked like this:

  IRecordsetProvider = interface(IDispatch)
  ['{CB8CDFA1-C536-11D4-8481-E82B82956957}']
    function  Get_Recordset: _Recordset; safecall;
    procedure Set_Recordset(const Value: _Recordset);      
                                        safecall;
    property Recordset: _Recordset read Get_Recordset 
                                   write Set_Recordset;
  end;

In the corresponding TRecordSetProvider class, I added an 
FRecordset private field. I had to put Ador_TLB in the uses 
clause (the file had been generated for me automatically). 
Then I filled in the methods to assign and retrieve the 
recordset property, e.g. 

function TRecordsetProvider.Get_Recordset: _Recordset;
begin
  Result := FRecordset;
end;

The only thing left to do was to create the recordset. I 
did that in an overridden Initialize method - you can't use 
constructors with COM objects, because they're created 
through class factories, so you do resource creation in 
Initialize. Here's a little example:

procedure TRecordsetProvider.Initialize;
begin
  inherited;
  FRecordset := 
    CreateComObject(CLASS_Recordset) as _Recordset;
  FRecordset.CursorLocation := adUseClient;
  
  { Create the recordset's fields }
  FRecordset.Fields.Append('FirstName', adBSTR, 
                 0, adFldUnspecified, EmptyParam);
  FRecordset.Fields.Append('Surname', adBSTR, 0,           
          adFldUnspecified, EmptyParam);
  FRecordset.Fields.Append('EmailAddress', adBSTR, 
                 0, adFldUnspecified, EmptyParam);
  FRecordset.Open(EmptyParam, EmptyParam,
         adOpenUnspecified, adLockUnspecified, 1);
         
  { Add a record }
  FRecordset.AddNew(
       VarArrayOf([Widestring('FirstName'),                
                   Widestring('Surname'),                  
                   Widestring('EmailAddress')]), 
       VarArrayOf([Widestring('Deborah'),
                   Widestring('Pate'),                     
                  Widestring('dpate@hotmail.com')]));
  FRecordset.Update(EmptyParam, EmptyParam);
end;

I'm very new to ADO myself, so I don't cite this as an 
example of good code by any means. But it seems to work, at 
least. :) I can call this automation object from a client 
Delphi application like this:

var
  RS: OleVariant;
begin
  RS :=         
CreateOleObject('DebsComplessADO.RecordsetProvider');
  Caption := RS.Recordset.Fields['FirstName'].Value;

and it should work with the equivalent VB code without 
difficulty.

-- 
Deborah Pate (TeamB)
http://delphi-jedi.org
Sorry, no email please.

    Source: geocities.com/huanlin_tsai/faq

               ( geocities.com/huanlin_tsai)