Как изменить вычисляемое поле с помощью TADODataSet?

У меня есть TADODataset, выполненный с (только для примера):

SELECT id, name, lastname, name + ' ' + lastname as fullname
FROM persons
ORDER BY lastname

После открытия набора данных я могу изменить поля "name" и "lastname", но не могу изменить "fullname", потому что он вычисляется.

Я пытаюсь открыть TADODataset в TClientDataset через DataProvider, но это занимает слишком много времени (в исходном наборе данных около 100 тысяч записей):

SrcDS.FieldDefs.Update;
for i := 0 to Pred(SrcDS.FieldDefs.Count) do
  SrcDS.FieldDefs[i].CreateField(SrcDS).ReadOnly := false;
DestDS := TClientDataset.Create(nil);
DestDS.SetProvider(SrcDS);
DestDS.Open;
DestDS.SetProvider(nil);

В общем, я хочу иметь независимый набор данных с изменяемыми полями.
Как мне изменить вычисляемые поля в наборе данных?


person a.vakhrushev    schedule 15.03.2013    source источник
comment
Вы хотите, чтобы полное имя было редактируемым, и что дальше? Вы не можете записать его обратно в базу данных (если только вы не проанализируете его обратно на имя и фамилию в обработчике событий, что подвержено ошибкам). Чего вы пытаетесь достичь с полным именем?   -  person Jan Doggen    schedule 15.03.2013
comment
Я не хочу записывать его обратно в базу данных. Набор данных связан с компонентом TcxGrid. Я хочу изменить набор данных только на клиенте, поэтому изменения будут отображаться в компоненте.   -  person a.vakhrushev    schedule 15.03.2013
comment
Вы меняете полное имя, изменяя его компоненты... Какой смысл разрешать редактирование полного имени, если вы не записываете их в ответ? Разве что вы будете разделять новое полное имя и записывать результаты разделения в поля имени/фамилии? В этом случае: вам будет очень весело с мультикультурными именами.   -  person Marjan Venema    schedule 15.03.2013
comment
Это был только пример для демонстрации вычисляемого поля   -  person a.vakhrushev    schedule 15.03.2013
comment
+1 Хороший вопрос. В какой-то момент я пытался добиться такого же поведения. мой вывод был, это не может быть сделано. даже с LockType = ltBatchOptimistic вы могли редактировать вычисляемое поле, но я не нашел способа запретить провайдеру не обновлять изменения, внесенные в поле вычислений во время UpdateBatch.   -  person kobik    schedule 15.03.2013
comment
Вам, вероятно, потребуется отменить все изменения в fullname, прежде чем делать ApplyUpdates. Таким образом, провайдер увидит, что ему не нужно ничего менять. Другим вариантом может быть использование обработчика событий onBeforeUpdateRecord компонента DataSetProvider для написания собственного SQL. См. это Создание приложений с помощью ClientDataSet и InterBase Express, подзаголовок Обновление наборов данных, которые нельзя обновить.   -  person EMBarbosa    schedule 06.11.2013
comment
Кроме того, очень похожий вопрос: stackoverflow.com/questions/13505612/   -  person EMBarbosa    schedule 07.11.2013


Ответы (1)


Вы должны рассчитать поле в Delphi. Создайте новое поле, щелкнув правой кнопкой мыши компонент TADODataset, выберите New Field, дайте ему имя и установите тип «вычисленный».

В OnCalculateFields-Event просто напишите:

Procedure TMyDataModule.MyDatasetCalculate(Sender : TDataset);
Begin
  MyDataSetFullName.AsString := MyDatasetFirstName.AsString+' '+MyDataSetLastName.AsString;
End;

Обновление: Что касается вашей второй проблемы (100 000 записей): если вы загрузите их в свой набор данных ADO, используя LockType = ltBatchOptimistic, это будет достаточно быстро, и ничего не будет сохранено в базе данных, если вы не вызовете метод UpdateBatch.

Если это все еще слишком медленно, попробуйте использовать функцию асинхронной загрузки (см. ExecuteOptions)

person alzaimar    schedule 15.03.2013
comment
Печально, но факт: мне нужно изменить текущий набор данных или быстро создать его копию - person a.vakhrushev; 15.03.2013
comment
мне нужно изменить текущий набор данных или быстро создать его копию ?? Что это обозначает - person Jan Doggen; 15.03.2013
comment
Только изменять набор данных, а не записывать его обратно в базу данных. - person a.vakhrushev; 15.03.2013
comment
Хорошо, и вы все еще хотите, например. изменить имя, и полное имя также автоматически изменится? Затем вы можете использовать LockType = ltBatchOptimistic и, наконец, отменить/отменить изменения. Но расчет поля все равно придется делать в Delphi (естественно) - person alzaimar; 15.03.2013
comment
Мне больше не нужны автоматические изменения полного имени, только набор данных с полями, которые я могу изменить - person a.vakhrushev; 15.03.2013
comment
@Tona, изменяйте только набор данных, а не записывайте его обратно в базу данных. Вы не хотите записать имя, фамилию обратно в БД? если да, alzaimar дал вам правильный ответ. - person kobik; 15.03.2013