8

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

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    |  
-------------------------------------
4

3 回答 3

8

您可以DataSet修改它以更改其在/上的Modified属性(并设置初始/默认值)并稍后测试(例如,在发布之前)。 为了确定修改了哪些特定字段,我持有初始记录的副本,例如:AfterInsertAfterEditDataSet.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组件中实现此功能。

于 2012-04-05T07:47:39.937 回答
3

当状态为 dsInsert 时,使用:

VarCompareValue(Field.NewValue, Unassigned) = vrNotEqual;

dsEdit 使用:

OldValue <> Value;

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

Field.NewValue <> Unassigned
于 2012-04-04T16:02:29.493 回答
0

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

从我到现在对应用程序执行的测试来看,这种解决方法似乎是有效的。我现在需要调查所有发生的事件并且需要特殊处理以不改变进程中全局变量的状态。

欢迎任何其他想法

于 2012-04-05T14:12:50.107 回答