Subject | Bugfix for TDataset components |
---|---|
Author | Jason Wharton |
Post date | 2006-01-07T20:45:15Z |
Please update your IBOTDataset.pas unit with this modified procedure if you
access field data values in the OnStateChange event and your dataset uses
inserts. What happens is the buffers in the dataset are not resync() until
after the state is changed and so I have to manually hack the TDataset
buffer in order to avoid a reference to a stale pointer.
procedure TIBODataset.InternalCancel;
var
tRecInfo: PIBORecInfo;
begin
if InternalDataset.NeedToPost then
InternalDataset.Cancel;
if FCurRowNum <> InternalDataset.RowNum then
begin
FCurRowNum := InternalDataset.RowNum;
CursorPosChanged;
end
else
// Need to hack the buffers so that it will pick up the new content in
place
// of the previously cancelled insert, which are now invalid pointers.
// Resync() will clean up the rest later on when other records are needed.
// The problem being solved here manifested in the OnStateChange event
showing
// the values from the cancelled record instead of the current record.
// It could have also been showing junk data from stale pointers too.
// The InternalDataset has already done the cancel but the TDataset has
not
// yet finished. I'll need to watch to see if Borland does anything to
// make it so that people don't have to work around this deficiency in the
// future.
if State = dsInsert then
begin
tRecInfo := PIBORecInfo(ActiveBuffer + FRecInfoOfs);
tRecInfo.RecRowNum := InternalDataset.RowNum;
tRecInfo.RecRowNode := InternalDataset.Fields.RowNode;
tRecInfo.BookmarkFlag := bfCurrent;
end;
FRecAppended := false;
end;
The fix here is thanks to a generous soul who provided an excellent sample
application.
Jason Wharton
access field data values in the OnStateChange event and your dataset uses
inserts. What happens is the buffers in the dataset are not resync() until
after the state is changed and so I have to manually hack the TDataset
buffer in order to avoid a reference to a stale pointer.
procedure TIBODataset.InternalCancel;
var
tRecInfo: PIBORecInfo;
begin
if InternalDataset.NeedToPost then
InternalDataset.Cancel;
if FCurRowNum <> InternalDataset.RowNum then
begin
FCurRowNum := InternalDataset.RowNum;
CursorPosChanged;
end
else
// Need to hack the buffers so that it will pick up the new content in
place
// of the previously cancelled insert, which are now invalid pointers.
// Resync() will clean up the rest later on when other records are needed.
// The problem being solved here manifested in the OnStateChange event
showing
// the values from the cancelled record instead of the current record.
// It could have also been showing junk data from stale pointers too.
// The InternalDataset has already done the cancel but the TDataset has
not
// yet finished. I'll need to watch to see if Borland does anything to
// make it so that people don't have to work around this deficiency in the
// future.
if State = dsInsert then
begin
tRecInfo := PIBORecInfo(ActiveBuffer + FRecInfoOfs);
tRecInfo.RecRowNum := InternalDataset.RowNum;
tRecInfo.RecRowNode := InternalDataset.Fields.RowNode;
tRecInfo.BookmarkFlag := bfCurrent;
end;
FRecAppended := false;
end;
The fix here is thanks to a generous soul who provided an excellent sample
application.
Jason Wharton