Я только что заметил странное поведение (конечно, Oracle, вероятно, должен вести себя таким образом, но это еще не вписывается в мое мировоззрение):
Я пытаюсь вставить две строки в родительский идочерняя таблица, обе в одной и той же транзакции:
INSERT INTO V_Parent (ID, Name) VALUES (777, 'Hello World');
INSERT INTO T_Child (ParentID, Name) VALUES (777, 'Foo Bar');
Дочерняя таблица имеет ограничение внешнего ключа (ParentID) references Parent.ID
.
Во втором операторе Oracle происходит сбой с сообщением об ошибке «Родительский ключ не найден.»
Если я отключу ограничение FK, это сработает.Я утверждал, что ParentID и Parent.ID совпадают, и я на 100% уверен, что первая строка успешно выполнена перед второй.Далее я попытался зафиксировать каждое утверждение, которое работало нормально.
Однако , как показывают префиксы в моем примере кода, первый INSERT фактически выполняется для представления родительской таблицы.Причина в том, что я использую NHibernate, а отображение использует представление в фоновом режиме (что до сегодняшнего дня не вызывало никаких проблем).
Q1: Возможно, вставка в представление отложена в Oracleчтобы второй оператор завершился неудачей?
Q2: Как я могу решить эту проблему лучше всего?
- Нужно ли определять триггеры INSTEAD OF навиды?
- Можно ли изменить настройку в определении VIEW?
- Можно ли изменить настройку в определении FOREIGN KEY?
- (I не должен сгибает отображение гибернации к исходной таблице: требуется использование представлений, чтобы изменения и / или проблемы безопасности могли быть скрыты за представлениями)
Подробности: C # WinForms Application -NHibernate - Oracle 10.2 - T_Child: Рано или поздно я тоже буду использовать представление для этой таблицы, просто оно еще не определено.
Редактировать : Подробнее по комментариям:
- ID назначается NHibernate с использованием последовательности Oracle (
<generator class="sequence">
) и является частью оператора INSERT, как в моем примере.Я также проверил, что полученный идентификатор в строке таблицы соответствует одному NHibernate, сохраненному в сопоставленном объекте. - Представление определяется как SELECT, который СОЕДИНЯЕТ некоторые поля других таблиц.Однако при вставке / обновлении я изменяю только поля, принадлежащие основной таблице ("T_PARENT"), и это обычно работает нормально.
- Текущее ограничение внешний ключ равно , а неdeferrable , но это не должно иметь никакого эффекта, поскольку родительский оператор выполняется перед дочерним оператором.*)
*) Хм ... позвольте мне подумать: поскольку я использую сеанс NHibernate для отправки запросов SQL, может случиться так, что NHibernate выполнит их в другом порядке, чем я говорилэто к?
Я буду исследовать это. => Кажется, посмотрите мой собственный ответ.
Вот так выглядит реальный код:
ISession session = this.DAOFactory.NHibernateHelper.SessionFactory.OpenSession();
ITransaction tx = session.BeginTransaction();
try
{
// parent.ID == 0
session.SaveOrUpdate(parent);
// parent.ID == 777 (for example)
ISQLQuery query = session.CreateSQLQuery(
"INSERT INTO T_CHILD (PARENT_ID, NAME) VALUES (:parentId, :name)");
query.SetDecimal("parentId", parent.ID);
query.SetDecimal("name", "Foo Bar");
query.ExecuteUpdate(); // Fails with ORA-Exception
tx.Commit();
}
catch (Exception)
{
tx.Rollback();
throw;
}
finally
{
session.Close();
}