8

データセットが既に挿入状態にあるときに、データベース対応コンポーネント フィールドが変更されたかどうかを確認するにはどうすればよいですか? フィールドが「本当に」変更されたかどうかを知りたいです。(ユーザーがフィールドに何かを入力した後、すべてを消去したかどうかは気にしません。これは、変更が発生したことを意味します)。

DataSet.ModifiedDataSet.UpdateStatusまたは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    |  
-------------------------------------
4

3 に答える 3

8

をハックして/のプロパティDataSetを変更し(および初期値/デフォルト値を設定)、後でテストすることができます(たとえば、投稿前に)。 どの特定のフィールドが変更されたかを判断するために、最初のレコードのコピーを保持しています。ModifiedAfterInsertAfterEditDataSet.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;

数値フィールド 0 と等しいので、dsInsert 状態でこれを使用しないでください。

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

今まで私は解決策を見つけましたが、それはうまくいくようです。解決策は次のとおりです。-データソースをtdatasetの子孫にリンクします-グローバルブール変数は、データセットのOnAfterScrollイベントではfalseに設定され、データソースのOnDataChangeイベントではtrueに設定されます。

私がアプリケーションで実行したテストから現在まで、この回避策は機能しているようです。ここで、発生するすべてのイベントを調査する必要があり、プロセス内のグローバル変数の状態を変更しないための特別な処理が必要です。

他のアイデアは大歓迎です

于 2012-04-05T14:12:50.107 に答える