rs.Set_ActiveConnection(
null);
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);
它适用于Delphi 5
问题是我无法在Delphi XE6中运行它.在Delphi 5中我会成功调用:
rs.Set_ActiveConnection(nil);
一切都很精彩.它起作用,因为_Recordset接口被声明为:
procedure Set_ActiveConnection(const pvar: IDispatch); safecall;
通过nil是有效的;它工作.
在XE6中,退出变为:
procedure Set_ActiveConnection(pvar: OleVariant); safecall;
你不能通过零.那么问题就是,OleVariant相当于nil是什么?
试试#1
//Disconnect the recordset by setting the .ActiveConnection to null rs.Set_ActiveConnection(nil); //E2010 Incompatible types: 'OleVariant' and 'Pointer'
试试#2
//Disconnect the recordset by setting the .ActiveConnection to null rs.Set_ActiveConnection(Null);
导致异常:
Arguments are of the wrong type,are out of acceptable range,or are in conflict with one another
试试#3
//Disconnect the recordset by setting the .ActiveConnection to null rs.Set_ActiveConnection(EmptyParam);
导致异常:
Arguments are of the wrong type,or are in conflict with one another
试试#4
//Disconnect the recordset by setting the .ActiveConnection to null rs.Set_ActiveConnection(Unassigned);
导致异常:
Arguments are of the wrong type,or are in conflict with one another
试试#5
//Disconnect the recordset by setting the .ActiveConnection to null rs.Set_ActiveConnection(OleVariant(nil)); //E2089 Invalid typecast
试试#6
//Disconnect the recordset by setting the .ActiveConnection to null rs.Set_ActiveConnection(OleVariant(Null));
导致异常:
Arguments are of the wrong type,or are in conflict with one another
试试#7
我很清楚,Codebarcadero声明错误.它应该是一个IDispatch.这意味着我需要欺骗编译器传递位于地址0x00000000(即nil)的OleVariant.这样ADO会在堆栈上看到值0x00000000,并且我知道我的意思是null:
rs.Set_ActiveConnection(POleVariant(nil)^); //access violation before call
我肯定Bo..Imp …… Co..Embarcadero有打算调用它的方法;我只是想不出来.
Delphi 5组装
Dephi 5做的正确;它将$00(即nil)推入堆栈:
rs.Set_ActiveConnection(无);
推$0;推nil
mov eax,[ebp- $08];获取rs的地址
推eax;推“这个”
mov eax,[eax];得到IRecordset的VMT
call dword ptr [eax $28];拨打FMT抵消28美元
而Delphi XE6正在经历英勇的努力,做一些我不知道的事情:
rs.Set_ActiveConnection(无);
lea eax,[ebp- $000000d8]
叫Null
lea edx,[ebp- $000000d8]
lea eax,[ebp- $000000c8]
致电@OleVarFromVar
push dword ptr [ebp- $000000bc]
push dword ptr [ebp- $000000c0]
push dword ptr [ebp- $000000c4]
push dword ptr [ebp- $000000c8]
mov eax,[ebp- $04]
推eax
mov eax,[eax]
叫dword ptr [eax $2c]
奖金阅读
> MSDN: Disconnecting and Reconnecting the Recordset
> KB184397: How To Create ADO Disconnected Recordsets in VBA/C++/Java
> MSDN: Recordset Object (ADO)
> MSDN: ActiveConnection Property (ADO)
解决方法
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在变体后的版本中 – 基于OLE自动化添加(D2),编译器已知如何生成代码以在OleVariant和IDispatch接口之间双向转换.所以“问题”是如何将IDispatch接口作为OleVariant参数传递.这一点,以我简单的方式来看待它,很简单,只需编写IDispatch(),其中参数应该是OleVariant,并让编译器对要生成的代码进行排序.如果我们想要作为IDisaptch接口传递的值实际上是Nil,我们只需要编写
SomeInterfaceMemberExpectingAnOleVariant(IDispatch(Nil))