在 ADOQuery 中使用参数时出错

Error when using parameter in ADOQuery

我有这个简单的代码来检查 table 中是否存在记录,但它总是 returns 运行时错误:

Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.

我的代码是这样的:

function TDataModuleMain.BarCodeExists(barCode: string): boolean;
begin
   if ADOQuerySql.Active then
     ADOQuerySql.Close;

   ADOQuerySql.SQL.Clear;
   ADOQuerySql.SQL.Text := 'select count(1) from Card where BarCode = (:TestBarcode)';
   ADOQuerySql.Parameters.ParamByName('TestBarcode').Value := barCode;

   ADOQuerySql.Open; // HERE THE RUNTIME ERROR APPEARS

   Result := ADOQuerySql.Fields[0].AsInteger = 1;
   ADOQuerySql.Close;
   ADOQuerySql.Parameters.Clear;
end;

table Card 中的字段 BarCode 是 nvarchar(100) 类型

在调试中,我看到参数已创建,并填充了正确的值。
运行 sql 服务器管理工​​作室中的查询也有效。

我也发现了这个 How to pass string parameters to an TADOQuery? 并用答案中的代码检查了我的代码,但我没有发现任何问题。
另外这个 AdoQuery Error using parameters 对我没有帮助。

毫无疑问,我错过了一些非常简单的东西,但我现在看不到它。

编辑:我根据评论中的建议尝试过的事情:

.ParamCheck := True (default)  
.Parameters.ParamByName('TestBarcode').DataType := ftString  
.Parameters.ParamByName('TestBarcode').DataType := ftWideString  
然而,

None 有效。

有用的是为此使用了一个非共享的 AdoQuery,并且它没有任何错误地完成了这项工作。我现在正在使用它作为解决方案,但出于好奇,我仍在查看共享的 AdoQuery 究竟是什么问题。

编辑:找到问题的根源。

我使用 MartinA 提供的函数来检查动态创建的查询和共享的 AdoQuery,我发现了一个区别。
共享的 AdoQuery 已填充此 属性:

ExecuteOption := [eoExecuteNoRecords]

而动态创建的查询则没有。
由于此 属性 未在设计时设置,因此我没有看到它。 清除 属性 到 [] 后,共享 AdoQuery 再次工作。
我将按照建议切换到使用非共享 AdoQuery 进行此类工作。

感谢大家的帮助。

以下并不是对您问题的完整回答,而是为了跟进我对 "all you have to do is to inspect your form's DFM and compare the properties of your original ADoQuery with the unshared one. The answer should lie in the difference(s)" 的评论以及您对非共享查询是动态创建的回复。

两个 ADOQuery 之间的行为差​​异不涉及 "voodoo"。这只是捕捉实际差异的问题。

因此,要自己调试问题,您需要一些代码来比较两个组件的属性,即使其中一个或两个组件是动态创建的。在两个组件上使用以下例程将使您能够做到这一点:

function TForm1.ComponentToString(AComponent : TComponent) : String;
var
  SS : TStringStream;
  MS : TMemoryStream;
  Writer : TWriter;
begin
  //  Note:  There may be a more direct way of doing the following, without
  //  needing the intermediary TMemoryStream, MS
  SS := TStringStream.Create('');
  MS := TMemoryStream.Create;
  Writer := TWriter.Create(MS, 4096);

  try
    Writer.Root := Self;
    Writer.WriteSignature;
    Writer.WriteComponent(AComponent);
    Writer.FlushBuffer;
    MS.Position := 0;
    ObjectBinaryToText(MS, SS);
    Result := SS.DataString;
  finally
    Writer.Free;
    MS.Free;
    SS.Free;
  end;
end;

交给你...