Delphi - TDataSet determines if it has been changed when it is in the insert / edit state

how to find out if the field of the data component has changed when the data set is already in the Insert state? I want to know if the "really" field has been changed. (I don’t care if the user enters something into the field and after that deletes everything, this means that a modification has occurred).

DataSet.Modified , DataSet.UpdateStatus or ChangeCount do not solve my problem.

LE: Let me explain this in more detail. so the original dataset looks like

------------------------------------- |PK | Field1| Field2| Field3|Field4| ------------------------------------- | 1 | a | b | c | d | ------------------------------------- 

after insertion

 ------------------------------------- |PK | Field1| Field2| Field3|Field4| ------------------------------------- | 2 | | | | | ------------------------------------- | 1 | a | b | c | d | ------------------------------------- 

when the data set is really changed

 ------------------------------------- |PK | Field1| Field2| Field3|Field4| ------------------------------------- | 2 | avalue| | | | ------------------------------------- | 1 | a | b | c | d | ------------------------------------- 
+7
source share
3 answers

You can hack a DataSet to change its Modified property to AfterInsert / AfterEdit (and set the initial / default values), and then check on the DataSet.Modified (for example, before publishing).
To determine which specific fields have been changed, I keep a copy of the initial entry, for example:

 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, this is an abstract idea anyway. You can subclass your TDataSet , like me, and implement this function directly inside your TDataSet component.

+8
source

When the dsInsert state uses:

 VarCompareValue(Field.NewValue, Unassigned) = vrNotEqual; 

Using dsEdit:

 OldValue <> Value; 

Do not use this in dsInsert state, as in numeric fields 0 equals Unassigned:

 Field.NewValue <> Unassigned 
+3
source

So far, I have found a solution that seems to work. The solution consists of: - linking the data source with the tdataset descendant - the global logical variable is set to false in the OnAfterScroll event dataset and is true in OnDataChange data sources .

From the tests that I have performed in the application so far, this seems to work. Now I need to investigate all the events that occur and need special treatment so as not to change the state of the global variable in the process.

Any other ideas are welcome.

0
source

All Articles