Delphi-TDataSet определяет, был ли он изменен, когда находится в состоянии вставки / редактирования

как я могу узнать, было ли изменено поле компонента с учетом данных, когда набор данных уже находится в состоянии вставки? Я хочу знать, было ли поле "действительно" изменено. (Мне все равно, если пользователь ввел что-то в поле, и после этого стереть все, это означает, что произошла модификация).

DataSet.Изменено, DataSet.Состояние обновления или ChangeCount не решают мою проблему.

LE: позвольте мне объяснить больше в глубже этого. Итак, начальный набор данных выглядит как

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

после вставки

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

когда набор данных действительно изменен

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

3 ответов


вы могли бы взломать DataSet изменить это Modified свойство on AfterInsert/AfterEdit (и установите начальные / значения по умолчанию) и более поздний тест для DataSet.Modified (например, на пред пост).
Чтобы определить, какие конкретные поля были изменены, я держу копию исходной записи, например:

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;

Ну, это абстрактная идея в любом случае. Вы могли бы подклассTDataSet как и я, и реализовать эту функцию непосредственно внутри вашего TDataSet компонент.


когда состояние dsInsert использовать:

VarCompareValue(Field.NewValue, Unassigned) = vrNotEqual;

использовать dsEdit:

OldValue <> Value;

не используйте это в состоянии dsInsert, так как в числовых полях 0 равно Unassigned:

Field.NewValue <> Unassigned

до сих пор я нашел решение, которое, кажется, работает. Решение состоит в: - связать источник данных с потомком tdataset - глобальная логическая переменная имеет значение false в dataset OnAfterScroll событие и true в источниках данных OnDataChange событие.

из тестов, которые я выполнял в приложении до сих пор, кажется, что эта работа работает. Теперь мне нужно расследовать все события, которые происходят и нуждаются в особом лечении не изменения состояния глобальной переменной в процессе.

любые другие идеи приветствуются