Delphi - Call locate of dataset connect to TDBGrid , without freeze the main thread

343 views Asked by At

Is it possible to call the function locate of dataset, without freezing the main thread, and ask the user if he wants to stop the function?

best regards;

thanks

EDIT 1

First code example

EDIT 2

Add comment to source with information of function call

I use ORACLE 11g of database , the dataset is a VIEW that return many record

I use for connect to oracle the component TOraQuery of DevArt with FetchRows set to 50

The locate is slow if the user enter the ID more distance from current fetch

this is the code that use for locate

procedure TForm1.GoToID(Id: integer; silent: boolean = false);
var KeyField  : string;
    T0        : TDateTime;
begin
  T0 := Now;
  if Not FQueryGrid.Active then
  begin
    { Function to write a log on file }
    LogModule.WriteLog('TForm1.GoToID', 'Query not active', tpliv3);
    Exit;
  end;

  if FQueryGrid.RecordCount = 0 then Exit;
  {FQueryGrid.DisableControls; No effect on performance}
  Try
  { GetKeyFieldForUpdateRecord Function with return the name of PRIMAY KEY 
       OF VIEW  
       CASE Type OF 
       1: RESULT := 'ID_DATA'; 
       2: RESULT := 'ID_TRACK';
       3: RESULT := 'ID_MACHINE'; 
    END;
  }
  KeyField := GetKeyFieldForUpdateRecord;
  try

    if Id > 0 then
    begin 
      {Check if ID request from user is egual at the current selected id}
      if Id = FQueryGrid.FieldByName(KeyField).AsInteger then
      begin
        {Function that save some fields on Record variable of current ID}
        SetBuild(True);
        Exit;
      end;
      { Freezing of main }
      if FQueryGrid.Locate(KeyField, Id, []) then
      begin
         {Function that save some fields on Record variable of current ID}
        SetBuild(True);
      end
      else
        if not silent then
          MessageBox(Handle, Pchar(STR_PROG_NOT_FOUND), 'Warning', MB_ICONWARNING or MB_OK or MODALITY);
    end;
  except
    on e: Exception do
      { Function to write a log on file }
      LogModule.WriteLog('TForm1.GoToID', e.Message, tpliv1);
  end;
  Finally
    //FQueryGrid.EnabledControls;   
  {$REGION 'Log'}
  {TSI:IGNORE ON}
  { Function to write a log on file with timing elpased for execute }
  LogModule.WriteLog(Format('[%p]%s.GoToID',[pointer(Self),Self.Classname]),
    Format('Execute in %s',[FormatDateTime(LOG_ID_343_2,Now-t0)]),tpliv5,True);
  {TSI:IGNORE OFF}
  {$ENDREGION}
  end;
end;

EDIT 3

Test with function FindKey

This function searches for the parameter passed to the function by using indexes specificata on the property INDEXNAME or INDEXFIELDNAME, the problem is that it searches only within fetched records and does not move the dataset for fetch new record

procedure TForm1.GoToID(Id: integer; silent: boolean = false);
var KeyField  : string;
    T0        : TDateTime;
begin
  T0 := Now;
  if Not FQueryGrid.Active then
  begin
    { Function to write a log on file }
    LogModule.WriteLog('TForm1.GoToID', 'Query not active', tpliv3);
    Exit;
  end;

  if FQueryGrid.RecordCount = 0 then Exit;
  {FQueryGrid.DisableControls; No effect on performance}
  Try
  { GetKeyFieldForUpdateRecord Function with return the name of PRIMAY KEY 
       OF VIEW  
       CASE Type OF 
       1: RESULT := 'ID_DATA'; 
       2: RESULT := 'ID_TRACK';
       3: RESULT := 'ID_MACHINE'; 
    END;
  }
  KeyField := GetKeyFieldForUpdateRecord;
  try

    if Id > 0 then
    begin 
      {Check if ID request from user is egual at the current selected id}
      if Id = FQueryGrid.FieldByName(KeyField).AsInteger then
      begin
        {Function that save some fields on Record variable of current ID}
        SetBuild(True);
        Exit;
      end;
      { Freezing of main }
      if FQueryGrid.FindKey([id]) then
      begin
         {Function that save some fields on Record variable of current ID}
        SetBuild(True);
      end
      else
        if not silent then
          MessageBox(Handle, Pchar(STR_PROG_NOT_FOUND), 'Warning', MB_ICONWARNING or MB_OK or MODALITY);
    end;
  except
    on e: Exception do
      { Function to write a log on file }
      LogModule.WriteLog('TForm1.GoToID', e.Message, tpliv1);
  end;
  Finally
    //FQueryGrid.EnabledControls;   
  {$REGION 'Log'}
  {TSI:IGNORE ON}
  { Function to write a log on file with timing elpased for execute }
  LogModule.WriteLog(Format('[%p]%s.GoToID',[pointer(Self),Self.Classname]),
    Format('Execute in %s',[FormatDateTime(LOG_ID_343_2,Now-t0)]),tpliv5,True);
  {TSI:IGNORE OFF}
  {$ENDREGION}
  end;
end;

EDIT 4

Decreasing performance

procedure TForm1.GoToID(Id: integer; silent: boolean = false);
var KeyField  : string;
    T0        : TDateTime;
    BFound    : Boolean;
begin
  T0     := Now;
  BFound := False;
  if Not FQueryGrid.Active then
  begin
    { Function to write a log on file }
    LogModule.WriteLog('TForm1.GoToID', 'Query not active', tpliv3);
    Exit;
  end;

  if FQueryGrid.RecordCount = 0 then Exit;
  {FQueryGrid.DisableControls; No effect on performance}
  Try
  { GetKeyFieldForUpdateRecord Function with return the name of PRIMAY KEY 
       OF VIEW  
       CASE Type OF 
       1: RESULT := 'ID_DATA'; 
       2: RESULT := 'ID_TRACK';
       3: RESULT := 'ID_MACHINE'; 
    END;
  }
  KeyField := GetKeyFieldForUpdateRecord;
  try

    if Id > 0 then
    begin 
      {Check if ID request from user is egual at the current selected id}
      if Id = FQueryGrid.FieldByName(KeyField).AsInteger then
      begin
        {Function that save some fields on Record variable of current ID}
        SetBuild(True);
        Exit;
      end;
      { Freezing of main }
      FQueryGrid.First;
      while not FQueryGrid.Eof do
      begin 
         if Id = FQueryGrid.FieldByName(KeyField).AsInteger then
         begin 
          {Function that save some fields on Record variable of current ID}
           BFound := True;

           SetBuild(True);
           Break;
         end;
        FQueryGrid.Next
      end;

      if not BFound then
        if not silent then
          MessageBox(Handle, Pchar(STR_PROG_NOT_FOUND), 'Warning', MB_ICONWARNING or MB_OK or MODALITY);
    end;
  except
    on e: Exception do
      { Function to write a log on file }
      LogModule.WriteLog('TForm1.GoToID', e.Message, tpliv1);
  end;
  Finally
    //FQueryGrid.EnabledControls;   
  {$REGION 'Log'}
  {TSI:IGNORE ON}
  { Function to write a log on file with timing elpased for execute }
  LogModule.WriteLog(Format('[%p]%s.GoToID',[pointer(Self),Self.Classname]),
    Format('Execute in %s',[FormatDateTime(LOG_ID_343_2,Now-t0)]),tpliv5,True);
  {TSI:IGNORE OFF}
  {$ENDREGION}
  end;
end;
0

There are 0 answers