Вставка родительских / дочерних записей в транзакцию - PullRequest
1 голос
/ 27 января 2011

У меня есть приложение на C #, которое должно вставить одну родительскую запись и как минимум четыре дочерних записи в иерархическом порядке. Таким образом, родительский Контракт применяется к одному или нескольким местоположениям, каждое местоположение имеет один или несколько элементов, каждый элемент имеет одну или несколько служб, и каждая служба имеет одно или несколько требований. Сначала приложение получает набор порядковых номеров Oracle, по одному из каждой последовательности таблиц для каждой записи. По какой-либо причине (устаревшая база данных) каждая запись имеет не только порядковый номер своего родителя, но также порядковый номер контракта.

Таким образом, код начинает транзакцию, вставляет родительский элемент с порядковым номером родительского уровня, затем пытается вставить запись местоположения - уже заполненную как родительским номером в виде FK, так и собственным порядковым номером таблицы. Тем не менее я получаю ошибку Oracle-02291, что FK нарушен, потому что родительский номер не может быть найден.

INSERT into Contracts (contract_sequence_number, ...) values (10437, ...);
INSERT into Locations (location_sequence_number, contract_sequence_number, ...) 
    values (23733, 10437, ...);
...

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

Я знаю, что это такой распространенный сценарий, ответ должен быть перед нубом. Но все ответы, которые я нашел до сих пор, подразумевают, что родительский порядковый номер находится «в таблице», чтобы удовлетворить FK.

Любые мысли о том, как это исправить, очень ценятся.

Randy

Ответы [ 5 ]

1 голос
/ 27 января 2011

Установите для своих fk-ограничений значение deferrable initially deferred.

Кроме того, вам необходимо выполнить обе / все вставки внутри одной транзакции.Если вы используете ODAC для C #, то сначала запустите OracleTransaction, выполните вставки, а затем commit () и dispose ().Убедитесь, что в блоке catch вызывается rollback () и dispose () для транзакции.

См. здесь для PDF-версии документации по компонентам доступа к данным Oracle (11g).

Надеюсь, что поможет

1 голос
/ 27 января 2011

Дочерние вставки будут видеть любого родителя, который был либо зафиксирован, либо был ранее вставлен той же транзакцией (независимо от того, зафиксирован или нет).

Одна вещь, чтобы проверить, является ли вставка родителя автоматически выводит значение первичного ключа (например, через триггер).

То есть вы выдаете заявление ВСТАВИТЬ в Контракты (contract_sequence_number, ...) значения (10437, ...);

но триггер определяет новый номер_последовательности_тракта из последовательности и фактически дает ему первичный ключ 10438 (или любой другой).

Другой проблемой может быть любой уровень ORM, который решает проблему, не выполняя вставки в правильном порядке или используя другие соединения из пула для одной «транзакции».

Также убедитесь, что вставка родительского элемента не вернула ошибку.

Попробуйте выполнить пример транзакции через обычный клиент (например, SQL * Plus) и посмотрите, работает ли он. Если дочерняя вставка завершается с ошибкой, просто запросите самую последнюю запись из контракта (например, где contract_sequence_number> 10400) и посмотрите, удалась ли вставка.

0 голосов
/ 04 марта 2011

Спасибо всем за ваш вклад. Оказалось (как я подозревал) это было плохо. Оказывается, есть две очень похожие схемы, и соединение, которое я использовал, имеет доступ к обеим. Обе схемы имеют таблицы с одинаковыми именами. По неясным для меня причинам родитель вставлял в одну схему, а ребенок пытался вставить в другую схему. Конечно, это не могло разрешить отношения PK / FK!

Еще раз спасибо.

0 голосов
/ 27 января 2011

я рекомендую вам проверить отложенные ограничения, которые будут проверять значения при фиксации его в базе данных, чтобы вы могли избежать ошибки FK not found

0 голосов
/ 27 января 2011

вставлены ли какие-либо вставки с параметром PRAGMA_AUTONOMOUS_TRANSACTION? мне кажется, что ожидающие коммиты должны быть видны всей транзакции.

О, еще одна мысль - если вставки находятся в триггере PRE, попробуйте переместить их в триггер POST.

...