如果你使用代码创建TClientDataSet, TDataSetProvider, TDataSet并将其关联起来 TClientDataSet->TDataSetProvider->TDataSet
但指定其TClientDataSet.ProviderName字符串在Open ClientDataSet 可能会出现如下问题:
invalid data packet
造成这个原因有两个:你的TClientDataSet, TDataSetProvider的Owner不是TComponent或不是同一个TComponent。我估计Delphi会在Owner按Name找TDataSetProvider。
解决的方法是使用ClientDataSet.SetProvider(TDataSetProvider);
但跟踪下SetProvider你会发现问题很复杂,因为使用这个方法将导致一些对象的创建,而且你每次Open ClientDataSet时都需要SetProvider。 这看起来问题更大了。
所以简单的解决方法是:
1、让ClientDataSet, TDataSetProvider的Owner相同且必须是TComponent。
2、如果你像我一样,Owner都不需要,那么你可以直接访问DataSetProvider.Data;连ClientDataSet都不需要。如果DataSetProvider是在另一台机器上,那么你还可以这么做:
function TDPDataAccess.GetDataByQuery(AADOConnection: TADOConnection; const ASQLStr: WideString;
const ADOSQLParameters: array of TADOSQLParameters): OleVariant;
var
i: Integer;
begin
ADOQuery.Close();
DataSetProvider.DataSet := ADOQuery;
ADOQuery.SQL.Text := ASQLStr;
ADOQuery.Connection := AADOConnection;
try
ADOQuery.Parameters.ParseSQL(ADOQuery.SQL.Text, True);
if (ADOQuery.Parameters.Count > 0) then
begin
for i := Low(ADOSQLParameters) to High(ADOSQLParameters) do
ADOQuery.Parameters.ParamByName(ADOSQLParameters[i].Name).Value := ADOSQLParameters[i].Value;
end;
ADOQuery.Open();
Result := DataSetProvider.Data;
finally
ADOQuery.Connection := nil;
end;
end;