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.