how can I find out if an data-aware component field has been modified when the dataset is already in Insert state? I want to know if a field was 'really' modified. (I don't care if the user has input something in a field and after that erase everything, this mean that a modification occured).
DataSet.Modified, DataSet.UpdateStatus or ChangeCount are not solving my problem.
LE: let me explain more in depth this. so, initial dataset looks like
-------------------------------------
|PK | Field1| Field2| Field3|Field4|
-------------------------------------
| 1 | a | b | c | d |
-------------------------------------
after insert
-------------------------------------
|PK | Field1| Field2| Field3|Field4|
-------------------------------------
| 2 | | | | |
-------------------------------------
| 1 | a | b | c | d |
-------------------------------------
when the dataset is really modified
-------------------------------------
|PK | Field1| Field2| Field3|Field4|
-------------------------------------
| 2 | avalue| | | |
-------------------------------------
| 1 | a | b | c | d |
-------------------------------------
You could hack the DataSet
to change it's Modified
property on AfterInsert
/AfterEdit
(and set initial/default values) and later test for DataSet.Modified
(e.g. on before post).
To determine which specific fields were modified, I hold a copy of the initial record e.g.:
type
TDataRecord = array of record
FieldName: string;
Value: Variant;
end;
type
TForm1 = class(TForm)
...
private
FInitRecord, FPostRecord: TDataRecord;
end;
function GetDataRecord(DataSet: TDataSet): TDataRecord;
var
I: Integer;
begin
Result := nil;
if Assigned(DataSet) then begin
SetLength(Result, DataSet.FieldCount);
for I := 0 to DataSet.FieldCount - 1 do begin
Result[I].FieldName := DataSet.Fields[I].FieldName;
Result[I].Value := DataSet.Fields[I].Value;
end;
end;
end;
type
TDataSetAccess = class(TDataSet);
procedure TForm1.ADODataSet1AfterInsert(DataSet: TDataSet);
begin
// set initial values
ADODataSet1.FieldByName('PK').Value := GetMyPKValue;
ADODataSet1.FieldByName('DateCreated').AsDateTime := Now();
// un-modify
TDataSetAccess(ADODataSet1).SetModified(False);
// save initial record
FInitRecord := GetDataRecord(ADODataSet1);
end;
procedure TForm1.ADODataSet1BeforePost(DataSet: TDataSet);
var
I: Integer;
begin
if ADODataSet1.Modified then
begin
FPostRecord := GetDataRecord(ADODataSet1);
Memo1.Lines.Clear;
for I := 0 to Length(FPostRecord) - 1 do begin
if FPostRecord[I].Value <> FInitRecord[I].Value then
Memo1.Lines.Add(Format('Field %s was modified', [FPostRecord[I].FieldName]));
end;
end;
end;
Well, It's the abstract idea anyway. You could sub-class your TDataSet
like I do, and implement this feature directly inside your TDataSet
component.
When the state is dsInsert use:
VarCompareValue(Field.NewValue, Unassigned) = vrNotEqual;
dsEdit use:
OldValue <> Value;
Do not use this in dsInsert state as in numeric Fields 0 is equal Unassigned:
Field.NewValue <> Unassigned
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With