如何在XE6中断开ADO记录集?

时间:2015-08-14 19:24:54

标签: delphi ado delphi-xe6

我正在尝试在XE6中使用断开连接的ADO Recordset 。我们的想法是您正常打开记录集,然后将记录集的 ActiveConnection 设置为您的语言等同于null / Nothing / {{ 1}}:

  

nil rs.Set_ActiveConnection(

Delphi 5中的以下示例工作正常:

);

适用于Delphi 5

问题是我无法在Delphi XE6中运行它。在Delphi 5中,我会成功致电:

var rs: _Recordset;

rs := CoRecordset.Create;
rs.CursorLocation := adUseClient; //the default for a Recordset is adUseServer (Connection.Execute's default is adUseClient)
rs.CursorType := adOpenForwardOnly; //the default
rs.Open(CommandText, Conn,
      adOpenForwardOnly, //CursorType
      adLockReadOnly, //LockType
      adCmdText);

//Disconnect the recordset by setting the .ActiveConnection to null
rs.Set_ActiveConnection(nil);

一切都很出色。它起作用,因为rs.Set_ActiveConnection(nil); 接口被声明为:

_Recordset

因此传递procedure Set_ActiveConnection(const pvar: IDispatch); safecall; 是有效的;它起作用了。

在XE6中,演化改为:

nil

您无法通过procedure Set_ActiveConnection(pvar: OleVariant); safecall; 。那么问题就是nil相当于OleVariant

尝试#1

nil

尝试#2

//Disconnect the recordset by setting the .ActiveConnection to null
rs.Set_ActiveConnection(nil); //E2010 Incompatible types: 'OleVariant' and 'Pointer'

导致异常:

  

参数类型错误,超出可接受范围或彼此冲突

尝试#3

//Disconnect the recordset by setting the .ActiveConnection to null
rs.Set_ActiveConnection(Null);

导致异常:

  

参数类型错误,超出可接受范围或彼此冲突

尝试#4

//Disconnect the recordset by setting the .ActiveConnection to null
rs.Set_ActiveConnection(EmptyParam);

导致异常:

  

参数类型错误,超出可接受范围或彼此冲突

尝试#5

//Disconnect the recordset by setting the .ActiveConnection to null
rs.Set_ActiveConnection(Unassigned);

尝试#6

//Disconnect the recordset by setting the .ActiveConnection to null
rs.Set_ActiveConnection(OleVariant(nil)); //E2089 Invalid typecast

导致异常:

  

参数类型错误,超出可接受范围或彼此冲突

尝试#7

我清楚Codebarcadero声明错误。它真的应该是//Disconnect the recordset by setting the .ActiveConnection to null rs.Set_ActiveConnection(OleVariant(Null)); 。这意味着我需要欺骗编译器传递位于地址IDispatch OleVariant (即nil)。这样ADO会在堆栈上看到值0x00000000,并且我知道我的意思是0x00000000

null

我确定Bo..Imp ...... Co..Embarcadero有打算调用它的方法;我只是想不出来。

Delphi 5汇编

Dephi 5做的正确;它将$ 00(即rs.Set_ActiveConnection(POleVariant(nil)^); //access violation before call )推入堆栈:

nil

尽管德尔福XE6正在通过英勇的努力去做一些我不知道的事情:

rs.Set_ActiveConnection(nil); push $0 ;push nil mov eax,[ebp-$08] ;get address of rs push eax ;push "this" mov eax,[eax] ;get VMT of IRecordset call dword ptr [eax+$28] ;call offset $28 of VMT

奖金阅读

1 个答案:

答案 0 :(得分:4)

在D7中(不要戴D5),AdoInt.Pas包含两种类型的Set_ActiveConnection,例如

  Recordset15 = interface(_ADO)
    ['{0000050E-0000-0010-8000-00AA006D2EA4}']
    procedure Set_ActiveConnection(const pvar: IDispatch); safecall;
    procedure _Set_ActiveConnection(pvar: OleVariant); safecall;

并在Delphi XE6中:

Recordset15 = interface(_ADO)
   ['{0000050E-0000-0010-8000-00AA006D2EA4}']
   //...
   procedure _Set_ActiveConnection(const pvar: IDispatch); safecall;
   procedure Set_ActiveConnection(pvar: OleVariant); safecall;

所以在XE6中尝试其他版本。就个人而言,我已经尝试了

Set_ActiveConnection(IDispatch(Nil)) 

首先,但你在评论中说_Set_ActiveConnection适合你。

我首先尝试使用Set_ActiveConnection(IDispatch(Nil))的原因,对于需要传递OleVariant的接口,是这样的:自从接口被添加到Delphi(在D3?中),iirc in添加基于变体的OLE自动化之后的版本(D2),编译器已经知道如何生成代码以在OleVariant和IDispatch接口之间双向转换。所以"问题"是如何将IDispatch接口作为OleVariant参数传递。这一点,以我简单的方式查看它,很简单,只需编写IDispatch(),其中参数应该是OleVariant,并让编译器对要生成的代码进行排序。如果我们想传递的,因为IDisaptch接口实际上是Nil,我们只需要编写

SomeInterfaceMemberExpectingAnOleVariant(IDispatch(Nil))