Delphi TFDStoredProc 参数默认值缺失(MS SQL)

问题描述 投票:0回答:1

我正在从 ADO 迁移到 FireDAC。将 TADOStoredProc 替换为 TFDStoredProc 后,我遇到以下问题。我的 _OpenStp 过程打开一个在其参数列表中具有默认值的存储过程,并且我不想传递所有这些参数。例如

CREATE PROCEDURE [dbo].[usp_SearchDocument]
  @User_Id INT
  , @Window_Id INT = 10
  , @Page INT = 1
...

我的程序的核心:

procedure _OpenStp(
  const AConnection: TFDConnection;
  var AStp: TFDStoredProc;
  const AStpName: string;
  const AParamNameA: array of string;
  const AParamValueA: array of Variant);
var
  i: Integer;
begin
  if AStp <> nil then
  begin
    if AStp.Active then
      AStp.Close;
  end
  else
    AStp := TFDStoredProc.Create(nil);

  AStp.Connection := AConnection;
  AStp.StoredProcName := AStpName;
  AStp.Prepare;
  for i := Low(AParamNameA) to High(AParamNameA) do
    AStp.Params.ParamByName(AParamNameA[i]).Value := AParamValueA[i];

  AStp.Open;
end;

调用的Delphi代码:

_OpenStp(SomeConnection, SomeStp, 'usp_SearchDocument',
  ['User_Id'], [150]);

根据 SQL Server Profiler,调用是:

exec [dbo].[usp_SearchDocument] 
  @User_Id=150,
  @Window_Id=NULL,
  @Page=NULL

TFDStoredProc.Prepare 似乎没有查询 sp 参数的默认值。当我使用 _OpenStp 过程的 ADO 对应项时,TADOStoredProc.Parameters.Refresh 方法完成了这项工作:

procedure _OpenStp(
  const AConnection: TADOConnection;
  var AStp: TADOStoredProc;
  const AStpName: string;
  const AParamNameA: array of string;
  const AParamValueA: array of Variant);
begin
  if AStp <> nil then
  begin
    if AStp.Active then
      AStp.Close;
  end
  else
    AStp := TADOStoredProc.Create(nil);

  AStp.Connection := AConnection;
  AStp.ProcedureName := AStpName;
  AStp.Parameters.Refresh;
  for i := 0 to Length(AParamNameA) - 1 do
    AStp.Parameters.ParamByName(AParamNameA[i]).Value := AParamValueA[i];

  AStp.Open;
end;

SQL Server 探查器:

exec usp_SearchDocument 150,default,default

不幸的是,无法重写代码来传递所有参数,我必须依赖 sp 参数默认值。有没有办法修改我的 _OpenStp 程序的 FireDAC 版本来实现此目标?

编辑:我什至没有有关参数类型的信息(请参阅 _OpenStp 过程),我只知道它们的名称和要设置的值,因此我无法以编程方式创建 TFDParams。

Edit#2:删除不必要的参数后抛出

EArgumentOutOfRangeException

for i := AStp.ParamCount - 1 downto 0 do
  if AStp.Params[i].Name <> '@RETURN_VALUE' then
  begin
    ExistsInArray := False;
    for j := Low(AParamNameA) to High(AParamNameA) do
      if Char.ToLower(AStp.Params[i].Name) = Char.ToLower(Format('@%s', [AParamNameA[j]])) then
      begin
        ExistsInArray := True;
        Break;
      end;

    if not ExistsInArray then
      AStp.Params.Delete(i);
  end;
sql-server delphi firedac
1个回答
0
投票

我们也遇到了同样的问题。删除参数后添加:

AStp.FetchOptions.Items := AStp.FetchOptions.Items - [fiMeta];
AStp.Unprepare;
AStp.Prepare;
© www.soinside.com 2019 - 2024. All rights reserved.