使用SQLDirect组件时,TClientDataset.ApplyUpdates失败并显示“不支持SQL”

时间:2016-04-20 13:30:37

标签: delphi delphi-10-seattle tclientdataset

从DelphiXE2更新到Delphi Seattle 10 Update 1后,我们在使用SQLDirect components版本6.4.5时执行TClientDataSet ApplyUpdates次调用时遇到问题

我制作了一个小测试应用程序 组件:TDBGrid -> TDataSource -> TClientDataSet -> TDataSetProvider -> TSDQuery -> TSDDatabase
查询为select * from tt_plan_task,提供商为UpdateMode=upWhereAll,ClientDataset为IndexFieldName=tt_plan_task_id 我们为字段tt_plan_task.tt_prj修改了一个值。

执行ApplyUpdates(0)时,代码会追溯到TSQLResolver.InternalDoUpdate中的DataSnap.ProviderUpdateKind=ukModify)。 在那里,生成的SQL和参数看起来像预期的那样 然后代码跳转到

procedure TSQLResolver.DoExecSQL(SQL: TStringList; Params: TParams);
var
  RowsAffected: Integer;
begin
  RowsAffected := (Provider.DataSet as IProviderSupportNG).PSExecuteStatement(SQL.Text, Params);

此语句因错误SQL not supported崩溃(Data.DBConsts中的SProviderSQLNotSupported)

但是由于这是一个界面,我无法进一步追踪 我不知道如何解决这个问题。 任何建议如何或可能会发生什么?

其他信息:

  • 通过TSDQuery组件执行SELECT和(参数化)UPDATE查询工作正常。
  • 将clientdataset与所有FireDac组件(TDBGrid -> TDataSource -> TClientDataSet -> TDataSetProvider -> TFDQuery -> TDFConnection)(不同的testapp)一起使用可以正常工作
  • 这是一个带有数据库方言3
  • 的FireBird数据库
  • FireBird版本为2.5.3.26778
  • Delphi 10安装时没有Interbase组件
  • 这一切都在Win7 VM中,其中删除了Delphi XE2(所有'Borland / CodeGear / Embarcadero'已清理掉),并安装了西雅图。我的同事在干净的Win10 VM中安装了干净的西雅图,存在类似的问题。
  • Apps和FireBird是Win32,操作系统是Win64

[注意:自我回答这个问题,因为我花了很长时间来解决这个问题。它可以帮助其他人。]

2 个答案:

答案 0 :(得分:0)

Googling the error message当我发现{@ 3}}时,我发现了一个用户与Oracle Direct Access存在类似问题的帖子。{它建议:

1)以性能为代价设置TDataSetProvider.ResolveToDataSet=true。这适用于测试应用程序。

2)第三方软件中可能未实现{覆盖} PSExecuteStatement,其data.db的基本程序开始执行:

function TDataSet.PSExecuteStatement(const ASQL: string; AParams: TParams): Integer;
begin
  Result := 0;
  DatabaseError(SProviderSQLNotSupported, Self);
end;

第二种情况就是发生了什么。 SQLDirect代码确实具有TSDDataSet方法的覆盖

function PSExecuteStatement(const ASQL: string; AParams: TParams; {$IFDEF SD_CLR} var ResultSet: TObject {$ELSE} {$IFDEF SD_VCL17} var ResultSet: TDataSet {$ELSE} ResultSet: TSDPtr = nil {$ENDIF} {$ENDIF}): Integer; overload; override;

在Delphi Seattle下解析/编译以覆盖:

function PSExecuteStatement(const ASQL: string; AParams: TParams; var ResultSet: TDataSet): Integer; overload; override;

没有
function TDataSet.PSExecuteStatement(const ASQL: string; AParams: TParams): Integer;

解决方案是添加一个:

在SDEngine.pas中的TSDDateSet的受保护方法中,更新如下:

function PSExecuteStatement(const ASQL: string; AParams: TParams): Integer; overload; override; // New override
function PSExecuteStatement(const ASQL: string; AParams: TParams; {$IFDEF SD_CLR} var ResultSet: TObject {$ELSE} {$IFDEF SD_VCL17} var ResultSet: TDataSet {$ELSE} ResultSet: TSDPtr = nil {$ENDIF} {$ENDIF}): Integer; overload; override;

实施:

function TSDDataSet.PSExecuteStatement(const ASQL: string; AParams: TParams): Integer;  // JD 20-4-2016
var
  ds: TDataSet;
begin
  ds := nil;
  Result := InternalPSExecuteStatement( ASQL, AParams, false, ds );
end;

答案 1 :(得分:0)

我在TAsaDataSet + TDataSetProvider + TClientDataSet上从Delphi 2009迁移到Seattle 10时遇到了类似的问题  我们解决了改变一些属性的问题:

AsaDataSet.readyOnly := true;
DataSetProvider.ResolveToDataSet := True;

然后在我们的代码的某个时刻,我们确保TAsaDataSet能够使用它的表。

TAsaDataSet .Close;
TAsaDataSet .Session  := DmConection.AsaConnection;
TAsaDataSet .SQL.Text := 'SELECT * FROM dba.table_name';
TAsaDataSet .Open;

我们还注意到从2009年到Seatle的方法签名OnGetTableName来自: (Sender: TObject; DataSet: TDataSet; var TableName: WideString);(Sender: TObject; DataSet: TDataSet; var TableName: string);

希望以某种方式帮助你。