поле автоинкремента "нарушение ключа" в ClientDataSet [Delphi] - PullRequest
1 голос
/ 20 февраля 2010

это мой третий вопрос здесь, пока отличные ответы ^^

У меня нет проблем с просмотром, редактированием данных, но вставками ...

Вот мое сомнение: В финансовом / фондовом программном обеспечении у меня есть форма для создания нового заказа,
естественно мне нужно вставить новую строку в t_orders table
и вставьте элементы в таблицу t_orderitems с полем orderId , связанным со строкой в ​​ t_orders

CREATE TABLE `t_orders` (
    `orderId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `clientId` INT(10) UNSIGNED NOT NULL,
    ...)

CREATE TABLE `t_orderitems` (
    `orderitemId` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `orderId` INT(10) UNSIGNED NOT NULL,
    ...)

--> INDEXES AND FOREIGN KEYS OMITTED <--

Как добавить порядок элементов в сетку и, наконец, нажать кнопку "FinalizeOrder"

  • Создать заказ в t_orders
  • Вставить элементы в t_orderitems , связанные с этим заказом

Соединение выполняется с помощью ADO.

Я не уверен, можно ли так поступить, в таком случае, как мне поступить?

edit: я пытался использовать вложенные ClientDataSets, и он работает по частям, но я все еще не знаю, как получить вставленный идентификатор заказа

edit2:
Теперь у меня есть другая проблема, я не могу добавить более одного элемента в ClientDataSet.
Поскольку OrderItemId пуст для всех элементов (я могу получить эти значения только при вставке базы данных), когда я пытаюсь добавить второй элемент, это дает мне Нарушение ключа, какие-либо идеи ??

Если я установил Updatemode на что-то отличное от upWhereKeyOnly и установил pfInKey на False, это работает, но я не думаю, что это опция

Есть идеи?

Заранее спасибо!
Артур.

Ответы [ 4 ]

1 голос
/ 21 февраля 2010

Если вы установили связь между основными данными между двумя наборами данных в вашем приложении, ADO может обработать это автоматически. Это означает, что после того, как вы вставите новую запись в набор основных данных (заказы), вы можете вставить новые записи в свой набор данных подробностей (order_items) без необходимости указывать order_id, потому что order_id для текущей записи в наборе основных данных будет автоматически получен вставлен во вновь вставленные записи набора данных деталей.

Чтобы установить отношения мастер / детали между вашими наборами данных, если вы используете AdoTable для набора подробных данных, вы можете установить его MasterSource на источник данных, связанный с вашим основным набором данных, и определить связь между двумя наборами данных, используя свойство MasterFields. Если вы используете AdoDataset или AdoQuery, вы должны установить для свойства DataSource подробный набор данных для источника данных, подключенного к вашему основному набору данных. Затем вы должны добавить предложение WHERE в оператор SQL набора подробных данных, используя параметр SQL с тем же именем, что и поле ключа в наборе основных данных. В вашем случае это будет примерно так:

SELECT * FROM t_orderitems WHERE OrderID = :OrderID

Теперь вы можете установить ваши отношения в свойстве MasterFields вашего набора подробных данных.

Поскольку в ваших заказах может быть несколько элементов, вы можете установить для LockType значение ltBatchOptimistic в наборе подробных данных (order_items), чтобы после добавления нового элемента он не отправлялся в базу данных немедленно. Использование ltBatchOptimistic означает, что ваши изменения будут сохраняться во временной памяти клиента до тех пор, пока вы не вызовете метод UpdateBatch. UpdateBatch отправляет все изменения в базу данных.

Если вы хотите отменить заказ, вы должны вызвать метод CancelBatch, чтобы отменить изменения, сделанные в наборе подробных данных, и вручную удалить созданную запись заказа в наборе основных данных.

1 голос
/ 20 февраля 2010

Я предполагаю, что у вас есть набор данных ADO, который получает данные из вашей БД и связан с сеткой? Для этого вам нужен промежуточный слой.

Создайте TClientDataset и подключите его к вашему набору данных ADO, затем подключите сетку к клиентскому набору данных. Когда приходит новый заказ, вызовите Append в клиентском наборе данных и вставьте в него данные для нового заказа. Это заставит это обнаружиться на сетке. Если вы хотите сохранить изменения в БД, вызовите .Update в наборе данных клиента. Он будет использовать набор данных ADO, с которым он связан, для отправки обновлений в БД. Проверьте документацию на TClientDataset для объяснения того, как все это настроить; это одна из немногих вещей в последних версиях, которые действительно хорошо документированы.

Чтобы обновить несколько таблиц, посмотрите документацию по отношениям мастер / подробности и используйте два набора данных, подобные этим, связанных друг с другом.

0 голосов
/ 21 февраля 2010
0 голосов
/ 21 февраля 2010

спасибо RRUZ, это не совсем то, что я хотел (мне все еще придется вручную устанавливать все элементы OrderId OrderId перед вставкой), но я сделаю это

with DataModule1.ADOQuery1 do
begin
  SQL.Text := 'SELECT LAST_INSERT_ID()';
  Open();
  First();
  LastInsertId := Fields[0].Value;
  Close();
end;
...