从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.Provider
(UpdateKind=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)
但是由于这是一个界面,我无法进一步追踪 我不知道如何解决这个问题。 任何建议如何或可能会发生什么?
其他信息:
TDBGrid -> TDataSource -> TClientDataSet -> TDataSetProvider -> TFDQuery -> TDFConnection
)(不同的testapp)一起使用可以正常工作[注意:自我回答这个问题,因为我花了很长时间来解决这个问题。它可以帮助其他人。]
答案 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);
希望以某种方式帮助你。