Обновление Я добавил пример кода ниже.Кроме того, когда я писал оригинальную версию этого ответа, я забыл, что одним из параметров TDataSetProvider является poAllowMultiRecordUpdates, но я не уверен, что это связано с вашей проблемой.
Сообщение об ошибке Unable to find record. No key specified
генерируется DataSetProvider, поэтому не подключается напрямую к вашему
QUeryCOnsulta.SQL.Text := 'DELETE FROM PORTICO_INICIAL;'
, потому что это обходит DataSetProvider.Ошибка происходит из-за неудачной попытки к ApplyUpdates
на CDS.Попробуйте изменить свой вызов на
Assert(cdsBDPortico_Inicial.ApplyUpdates(0) = 0);
, который покажет вам, когда произошла ошибка, потому что результат возврата ApplyUpdates
дает количество ошибок, которые произошли при его вызове.
Youскажем,
будет иметь повторяющиеся значения в некоторых случаях
Если это так, когда возникает проблема, это потому, что вы сталкиваетесь с фундаментальным ограничением работы DataSetProvider.Чтобы применить обновления к исходному набору данных, он должен сгенерировать SQL для отправки обратно на исходный набор данных (TSqlQuery1), который уникально идентифицирует строку для обновления в исходных данных, что невозможно, если исходный набор данных содержитдублированные строки.
По сути, вам нужно переосмыслить свой код, чтобы все строки набора исходных данных были уникальными.Как только вы это сделаете, установка DSP UpdateMode
на upWhereAll
должна избежать проблемы.Конечно, было бы лучше, если бы исходный набор данных имел первичный ключ.
Быстрый обходной путь - использовать CDS.Locate в цикле, куда вы вставляете записи, чтобы посмотреть, сможет ли он найтиуже существующая запись со значениями, которые вы собираетесь добавить.
Кстати, извините, что поднял вопрос о ProviderFlags.Это не имеет значения, если есть дублированные строки, потому что независимо от того, на что они установлены, DSP все равно не сможет обновить одну запись.
В случае, если это поможет, вот некоторый код, который может помочь заполнить вашу таблицу таким образом,что позволяет избежать дубликатовОн заполняет только первые два столбца, как в коде, который вы показываете в своей q.
function RowExists(ADataset : TDataSet; FieldNames : String; Values : Variant) : Boolean;
begin
Result := ADataSet.Locate(FieldNames, Values, []);
end;
procedure TForm1.PopulateTable;
var
Int1,
Int2,
Int3 : Integer;
i : Integer;
RowData : Variant;
begin
CDS1.IndexFieldNames := 'Int1;Int2';
for i := 1 to 100 do begin
Int1 := Round(Random(100));
Int2 := Round(Random(100));
RowData := VarArrayOf([Int1, Int2]);
if not RowExists(CDS1, 'Int1;Int2', RowData) then
CDS1.InsertRecord([Int1, Int2]);
end;
CDS1.First;
Assert(CDS1.ApplyUpdates(0) = 0);
end;