delphifiredactclientdatasetdelphi-10.4-sydney

Revisited: TClientDataset "Missing data provider or data packet"


With a dynamically created TFDQuery,TClientDataSet, and TDataSetProvider I bump into the "Missing data provider or data packet" with this code:

procedure ResetSavedPasswords(ADataModuleDataBaseAdmin : TDataModuleDataBaseAdmin);
var
   lQuery     : TFDQuery;
   lCDS       : TClientDataSet;
   lProvider  : TDataSetProvider;
begin
   lFrmBezig := TFormBezig.Create(nil);
   lQuery    := TFDQuery.Create(nil);
   lProvider := TDataSetProvider.Create(Application); 
   lCDS      := TClientDataSet.Create(nil);
   try
      lQuery.Connection := ADataModuleDataBaseAdmin.FDConnectionTimeTell;
      lQuery.CachedUpdates := true;
      lProvider.Options := lProvider.Options - [poUseQuoteChar];
      lProvider.DataSet := lQuery;
      lProvider.Name    := 'prvResetSavedPW';
      lCDS.ProviderName := lProvider.Name;
      lQuery.SQL.Text   := Format('select %s,%s from <owner>%s',[sMedMedID,sMedSavedPassword,SMedTabelNaam]),ADataModuleDataBaseAdmin;
      lCDS.Open;

Note that the created TDataSetProvider has an owner, based on this answer:

If DatasetProvider has no owner, ClientDataSet can not obtain a reference to the provider

But I still get the error. Opening the TFDQuery first shows me it has data.

What can be the reason?

Using FireDAC with Delphi 10.4. Sydney in a Win32 app.


Solution

  • It turns out that TClientDataSet needs an owner too:

    lCDS := TClientDataSet.Create(Application);
    

    This is obvious from the code that triggered the exception:

    function TCustomClientDataSet.GetAppServer: IAppServer;
    var
      ProvComp: TComponent;
      DS: TObject;
    begin
      if not HasAppServer then
      begin
        if ProviderName <> '' then
          if Assigned(RemoteServer) then
            FAppServer := RemoteServer.GetServer
          else if Assigned(ConnectionBroker) then
            FAppServer := ConnectionBroker.GetServer
          else
          begin
            if Assigned(Owner) then
            begin
              ProvComp := Owner.FindComponent(ProviderName);
              if Assigned(ProvComp) and (ProvComp is TCustomProvider) then
              begin
                DS := GetObjectProperty(ProvComp, 'DataSet');
                if Assigned(DS) and (DS = Self) then
                  DatabaseError(SNoCircularReference, Self);
                FAppServer := TLocalAppServer.Create(TCustomProvider(ProvComp));
              end;
            end;
          end;
        if not HasAppServer then
          DatabaseError(SNoDataProvider, Self);
      end;
      Result := FAppServer;
    end;
    

    The Assigned(Owner) fails, so the code does not bother looking for the TDataSetProvider