delphidelphi-2010fibplus

Issue with posting correct data with disablecontrols


I have been having some issues with using Disable/EnableControls() while iterating over a DataSet, namely when updating field(s).

What seems to be happening to the two updated fields, is that they are all taking the same data. It looks like the last value for the post is being entered for all rows. So lets say we have 3 records, that have updated values of 1, 2 and 3 (in my case, 3 is being posted for all fields) when I was expecting 1, 2 and then 3 for the last field.

For example, I have 10 records that are in my dataset. I run this function, upon looking at the grid, and persisting data the Cost column value is the same for each row, even though I have stepped through and put a watch on the getNewDataValue function, and they are different values.

NumberSelected = 0;
dataSourceItems.DataSet.DisableControls; //it this be my problem, accessing the dataset via the datasource? – I tried this and it didn’t make a difference.
while (NumberSelected < cxGridDBTableView1.Controller.SelectedRowCount) do
begin
  Id = cxGridDBTableView1.Controller.SelectedRows[NoSelected]).Values[0];
  if dataSourceItems.DataSet.locate('PK', Id, []) then 
  begin
    dataSourceItems.DataSet.edit;
    dataSourceItems.DataSet.fieldbyname('Cost').asfloat := getNewDataValue;
    dataSourceItems.DataSet.Post;
    inc(NumberSelected)
  end;

  dataSourceItems.DataSet.EnableControls;
end;

I am using Delphi 2010, DevExpress Quantum Grid, and FIBPlus datasets, accessing a Firebird database.

Looking over the documentation, I can see that when DisableControls() is called, TDataSet.DataEvent doesn't pass events to DataSources, and that all master detail relationships are broken, until EnableControls() is called. Could it be that I am accessing the DataSet on the DataModule via the DataSource? I have tried this, and it doesn't make a difference.

Without using Disable/EnableControls(), the speed is unusable. So any advice, or alternative way of iterating over a large DataSet at speed, would be helpful.


Solution

  • You are calling EnableControls() from inside the loop, when it should be outside the loop instead (preferably in a try..finally block).

    But more importantly, you are not incrementing NoSelected, so you are always accessing the same selected ID each time you make an edit. You have two variables fighting to doing the job that one variable should be doing by itself.

    Try this instead:

    NumberSelected = 0;
    dataSourceItems.DataSet.DisableControls;
    try
      while (NumberSelected < cxGridDBTableView1.Controller.SelectedRowCount) do
      begin
        Id = cxGridDBTableView1.Controller.SelectedRows[NumberSelected]).Values[0];
        if dataSourceItems.DataSet.Locate('PK', Id, []) then 
        begin
          dataSourceItems.DataSet.Edit;
          dataSourceItems.DataSet.FieldByName('Cost').AsFloat := getNewDataValue;
          dataSourceItems.DataSet.Post;
        end;
        Inc(NumberSelected);
      end;
    finally
      dataSourceItems.DataSet.EnableControls;
    end;
    

    Alternatively:

    dataSourceItems.DataSet.DisableControls;
    try
      for NumberSelected = 0 to cxGridDBTableView1.Controller.SelectedRowCount-1 do
      begin
        Id = cxGridDBTableView1.Controller.SelectedRows[NumberSelected]).Values[0];
        if dataSourceItems.DataSet.Locate('PK', Id, []) then 
        begin
          dataSourceItems.DataSet.Edit;
          dataSourceItems.DataSet.FieldByName('Cost').AsFloat := getNewDataValue;
          dataSourceItems.DataSet.Post;
        end;
      end;
    finally
      dataSourceItems.DataSet.EnableControls;
    end;