0

由于代码冗余,我将常用的 ADOQuery 处理概括为一个自己的方法,该方法返回查询的 _RecordSet。现在,当我检查该方法中的查询结果时,它们检查正常。但是返回的_RecordSet 似乎为空或nil(异常:EOleException 'Item cannot be found in the collection to the specific name or ordinal.')从我收集的信息来看,我似乎需要返回查询的_RecordSet的克隆。到目前为止,我已经尝试使用

res := qr.Recordset.Clone(adLockUnspecified); Result := res;,

TADOQuery.RecordSet._xClone()方法

不成功,以及这些方法,其中没有一个有效(几个组件无法识别,我猜是版本差异)。

我用于查询的代码:

function queryDb(const s: WideString; const dc: boolean = true): _RecordSet;
var
  ds: String;
  conn: TADOConnection;
  qr: TADOQuery;
  res: _RecordSet;
begin
  Result := nil;
  conn := TADOConnection.Create(nil);
  qr := TADOQuery.Create(nil);
  try
    ds := 'Provider=Microsoft.Jet.OLEDB.4.0;Data Source='
          + ExtractFilePath(Application.ExeName)
          + 'gdkp.mdb;Persist Security Info=False';
    conn.ConnectionString := ds;
    conn.LoginPrompt := false;
    conn.Connected := true;
    qr.Connection := conn;
    if(dc = true)then begin
      qr.DisableControls
    end;
    qr.SQL.Add(s);
    qr.Open;
    Result := qr.Recordset;
  finally
    conn.Free;
    qr.Free;
  end;
end;

之前是否有人克服过这个问题并知道合适的答案,或者可以引导我找到有用的内容?

4

2 回答 2

1

我不知道你的疯狂滑稽动作哪个更疯狂:

  1. 在函数内部设置并连接到数据库并在该函数内部进行查询,每次查询时都连接到数据库,这将非常缓慢。

  2. ADO 查询对象的生命周期应该比函数内部更长。这是一种代码气味,一种严重的气味。

  3. 将记录集保留在它所属的查询中。

  4. 普通人创建 TDataModules 并在他们的应用程序的生命周期中保留他们的对象,并使用以下代码重新查询:

    query.Active := false; query.Active := true;

每次您需要一些数据时,当它不必连接到数据库、创建和断开连接和查询时,请注意您的应用程序加速。

你到底在用你回来的 _recordsets 做什么?您是否在 C# 中学习过 ADO,并且您正在尝试在 Delphi 中使用 C# ADO.net 习惯用法?不。别那样做。

于 2012-07-07T13:23:48.153 回答
0

您返回的 RecordSet 是 nil/empty,因为您在 finally 语句中将其关闭。我猜这就是为什么您在返回之前尝试克隆 RecordSet 的原因?克隆它会创建另一个指向同一 RecordSet 的指针,因此关闭 RecordSet 也会导致您的克隆返回 nil/empty。

正如 Ben 所建议的,有更好的方法来做到这一点,比如使用 TDataModules,但这是我的方法:

我倾向于为每个数据检索或更新/插入操作编写一个函数。每个函数都作为参数传递一个 ADO 连接,然后运行查询/存储过程的内容包含在函数中,任何数据都作为 var 参数或返回值返回。我保留了一个 ADO 连接,它根据需要传递给每个函数。

eg(伪代码,因为我有一段时间没有做过Delphi)

function GetAllUsers(adoConnection : TAdoConnection) : TStringList    
begin
  result.clear;
  if (adoConnection <> nil) then
  begin
     ..
     ..
     // have already set up an ADOStoredProc called storedProc in this
     // part of the code block
     ..
    adoRec := storedProc.Execute();
    while not (adoRec.eof) do              // loop through record set and get our data
    begin
      result.Add(adoGetFieldStr(adoRec,'USERNAME'));    
      adoRec.MoveNext;
    end;
    adoRec.Free;
  end;
end

希望有帮助

于 2012-07-09T15:20:52.617 回答