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 событие.
из тестов, которые я выполнял в приложении до сих пор, кажется, что эта работа работает. Теперь мне нужно расследовать все события, которые происходят и нуждаются в особом лечении не изменения состояния глобальной переменной в процессе.
любые другие идеи приветствуются