2012-04-04 123 views
7

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

DataSet.Modified,DataSet.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 | 
------------------------------------- 
+0

如何直接询问控件?我的意思是'TDBEdit.Modified'?把它作为一个蹩脚的说明,请,我不是一个数据库感知控制用户:-) – TLama 2012-04-04 15:18:01

+1

@TLama - 问题是,这是包含在一个主要的形式/框架大量使用。因此,我试图找到一个通用的解决方案,它可以指示数据集是否真的在插入/编辑模式下发生了更改... – RBA 2012-04-04 15:26:03

+2

没有数据集级别的方式来执行此操作。只有数据感知控制方式才能做到这一点。 – 2012-04-04 22:16:04

回答

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组件内实施此功能。

3

当状态是dsInsert使用:

VarCompareValue(Field.NewValue, Unassigned) = vrNotEqual; 

DSEDIT使用:

OldValue <> Value; 

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

Field.NewValue <> Unassigned 
+1

这意味着要验证字段是否为空...变体null – RBA 2012-04-04 16:14:17

+0

没有完全得到您的评论,我发布的代码必须在实际记录中验证,通常在BeforePost事件中,它会告诉您它是否“真正”修改。 Post事件后,只需检查ChangeCount。 – 2012-04-04 16:23:44

0

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

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

欢迎任何其他想法

相关问题