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.
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;