Precis: Мой код пытается обновить нефизические поля в Delphi XE TClientDataset
(подключенном к TSQLQuery
с его набором свойств SQL
), которые были созданы в результате выполнения команды Open
во время выполнения.
У меня есть TClientDataset
, подключенный к TDatasetProvider
, подключенный к TSQLQuery
, подключенный к TSQLConnection
. Первые 3 из этих объектов инкапсулированы в пару классов в библиотеке, которую я использую во многих местах в нескольких проектах. Эти классы создают эти 3 объекта во время выполнения и устраняют значительное количество повторяющегося кода, необходимого, поскольку у меня много, много таких триплетов.
Обычно я загружаю TClientDataset
из базы данных, указав некоторый SQL в свойстве SQL
TSQLQuery
и вызвав Open
для TClientDataSet
. Fields
в TClientDataset
создаются с помощью этого вызова Open
, т.е. они не существуют до Open
.
Я столкнулся с проблемой в ситуации, когда три поля, сгенерированные в TClientDataset
, не являются физическими; то есть SQL выполняет вычисления для их генерации. К сожалению, в TClientDataset
эти 3 поля не создаются иначе, чем физические поля; их FieldKind
равно fkData
(в идеале должно быть fkInternalCalc
), свойство Calculated
равно False
(в идеале должно быть True
), а их ProviderFlags
включает pfInUpdate
(чего в идеале не должно быть). Неудивительно, что когда приходит время делать ApplyUpdates
на TClientDataset
, возникает исключение...
Project XXX.exe raised exception class TDBXError with message
SQL State: 42S22, SQL Error Code: 207 Invalid column name 'Received'.
SQL State: 42S22, SQL Error Code: 207 Invalid column name 'Issued'.
SQL State: 42S22, SQL Error Code: 207 Invalid column name 'DisplayTime'.
Я могу избежать этой ошибки, сняв флаги pfInUpdate
этих полей в обработчике событий OnUpdateData
TDatasetProvider
. Однако это решение требует, чтобы определенные имена полей были известны этой функции, которая находится в общих классах, упомянутых выше, что нарушает универсальность кода.
То, что я ищу, - это общее средство сигнализации о вычисляемом характере этих полей для функции обработчика событий.
Я не могу изменить их свойства FieldKind
или Calculated
(на fkInternalCalc
и True
соответственно) после вызова Open
, так как это генерирует сообщение об исключении WorkCDS: Cannot perform this operation on an open dataset
. И я не могу изменить эти свойства до вызова Open
, так как Fields
еще не существует.
Я могу удалить флаг pfInUpdate
из свойств ProviderFlags
этих Field
после Open
, но это не будет передано "Дельте" TClientDatset
, которая поступает в обработчик событий OnUpdateData
. Я также попытался установить свойства поля FieldDefs.InternalCalcField
; опять же, это не передается в набор данных Delta.
Итак, все идеи сигнализации, которые я пробовал, не сработали. Буду признателен за любые новые идеи или альтернативный подход.
Все результаты поиска в Интернете, с которыми я столкнулся, включая превосходные статьи Кэри Дженсена, касаются настроек времени разработки или сгенерированных не SQL, которые не применимы к моей ситуации.
Open
TClientDataSet, а когда происходитApplyUpdates
. Я закодировал и успешно протестировал альтернативный подход, в котором я сохраняю указатель на предыдущий обработчик событийOnUpdateData
(EH) и устанавливаю новый локальный EH (первой задачей которого является вызов предыдущего EH). ЛокальныйOnUpdateData
EH содержит определенный код, очищающийProviderFlags
для каждого нефизического поля в наборе данных Delta. - person Chris Bargh   schedule 22.11.2012