Delphi - 当处于插入/编辑状态时,TDataSet确定它是否被修改

时间:2012-04-04 14:49:36

标签: delphi dataset delphi-2006

如何在数据集已处于插入状态时找出数据感知组件字段是否已被修改?我想知道一个字段是否真的被“修改”了。 (我不在乎用户是否在某个字段中输入了某些东西,然后擦除所有内容,这意味着发生了修改)。

DataSet.ModifiedDataSet.UpdateStatusChangeCount无法解决我的问题。

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 个答案:

答案 0 :(得分:8)

你可以在DataSet / Modified上修改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组件中实现此功能。

答案 1 :(得分:3)

当状态为dsInsert时使用:

VarCompareValue(Field.NewValue, Unassigned) = vrNotEqual;

dsEdit使用:

OldValue <> Value;

不要在dsInsert状态下使用它,因为数字字段0等于未分配:

Field.NewValue <> Unassigned

答案 2 :(得分:0)

直到现在我找到了一个似乎有效的解决方案。解决方案包括: - 将数据源链接到tdataset后代 - 数据集OnAfterScroll事件的全局布尔变量设置为false,数据源的OnDataChange事件设置为true。

从我在应用程序上执行的测试到目前为止,似乎这种解决方法正在发挥作用。我现在需要调查所有发生的事件,并且需要特殊处理,以便不改变过程中全局变量的状态。

欢迎任何其他想法