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

前端之家收集整理的这篇文章主要介绍了delphi – 如何在XE6中断开ADO记录集?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我试图在XE6中使用断开连接的ADO Recordset.这个想法是你正常打开记录集,然后你将记录集的ActiveConnection设置为你的语言相当于null / Nothing / nil:

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)

解决方法

在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在变体后的版本中 – 基于OLE自动添加(D2),编译器已知如何生成代码以在OleVariant和IDispatch接口之间双向转换.所以“问题”是如何将IDispatch接口作为OleVariant参数传递.这一点,以我简单的方式来看待它,很简单,只需编写IDispatch(),其中参数应该是OleVariant,并让编译器对要生成代码进行排序.如果我们想要作为IDisaptch接口传递的值实际上是Nil,我们只需要编写

SomeInterfaceMemberExpectingAnOleVariant(IDispatch(Nil))

猜你在找的Delphi相关文章