![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Внешние ключи в контекст транзации. [D7, IB 7.1]
Девушка © (2005-09-18 23:03:00)Хочу в одной транзации добавить сначала добавить запись в родительскую таблицу (справочник), потом, без commit-а добавить запись в дочернюю таблицу в которой в связанном посредством внешнего ключа поле ссылается на еще не подтвержденную родительскую запись.
Выдается ошибка Foreign Key.
Транзакция настроена на ReadCommited.
Добавление записей происходит из DBGridEH, а справочники прописаны как LookUp-поля.
Как добавить запись?
Пример:
Есть таблица товаров и таблица приходов.
1. Стартанули транзакцию.
2. Добавили новый товар "Конфеты".
3. Добавили новый приход с товаром "Конфеты" (здесь возникает ошибка)
4. Либо подтвердили, либо откатили всю транзацию.
Johnmen (2005-09-20 12:27:00) [1]>id-к получается через GeneratorField и Gen_ID в InsertSQL.
Кстати, это и есть запрос на следующий id Sergey13 © (20.09.05 10:11) [30], просто неявный.
И вообще, что-то мусолится, мусолится одно и то же...:)
Sergey13 (2005-09-20 12:08:00) [2]2[34] Девушка © (20.09.05 12:01)
>Как сделать так, что-бы не пришлось переоткрывать родительский набор данных?
А зачем его потом переоткрывать если он будет соответствовать действительности? Ты же этот родительский ИДшник можешь в дочку писать сразу.
Девушка (2005-09-20 12:01:00) [3]
> Sergey13 © (20.09.05 11:29) [33]
Вопрос может быть глупый, но как этот прием решит сабжевую проблему? Ну добавлю запись с ID-м который будет сгенерирован явно... это мне даст лишь возможность locat-ть заново запись. Как сделать так, что-бы не пришлось переоткрывать родительский набор данных?
Sergey13 (2005-09-20 11:29:00) [4]> Как вставлять явно через DNGridEH?
Опять вставлять через грид! 8-)
В InsertSQL
insrte into table_name(ID,......) values (:ID,....)
В BeforePost закататй в ИД-шник то что получишь от
Select Gen_Id(gen_name,1) from RDB$DATABASE
И тригер проверь. Должно быть условие на НУЛЛ.
Девушка (2005-09-20 11:23:00) [5]
> Кстати, проверьте опции коннекта. Там не должно быть SnapShot.
> И сколько у вас используется объектов транзакций ?
SnapShot-а нет. Транзакция одна
read_committed
rec_version
nowait
> Получи ИД-ник заранее и потом вставляй явно.
Как вставлять явно через DNGridEH?
msguns (2005-09-20 10:27:00) [6]>Девушка © (20.09.05 09:59) [29]
>Почему для того что-бы вставить запись в датасет дочерней таблицы, приходится перчитывать родительскую? Нелогично...
Чтобы вставить дочернюю таблицу новую запись с ID только что вставленной родительской записи на сервере, ничего перечитывать не надо.
А вот как работает FIBDataSet, точнее что и когда он там перечитывает - фиг его знает, однако что-то он делает "не так", потому и вылазит эксепшн.
Я сам им не пользуюсь именно потому, что не уверен на 100%, что он правильно "поймет", что я хочу. И приходится больше приноравливаться к его поведению, чем решать собственно стоящие задачи.
Ясно, что у Вас при связке Мастер-детал он при добавлении в гл.датасет что-то недоруливает.
Вот почему я и говорил, что для явногоуправления транзакциями лучше использовать TIBQuery.
Кстати, проверьте опции коннекта. Там не должно быть SnapShot. И сколько у вас используется объектов транзакций ?
Sergey13 (2005-09-20 10:11:00) [7]2[29] Девушка © (20.09.05 09:59)
ЕПРСТ. 8-)
Получи его ДО вставки
Select Gen_Id(gen_name,1) from RDB$DATABASE
В тригере поставь проверку на НУЛЛ
if new.id is null then new.id=Gen_Id(gen_name,1)
Получи ИД-ник заранее и потом вставляй явно.
Девушка (2005-09-20 09:59:00) [8]
> >2.Получать ИДшник родителя можно (и лучше) ДО вставки.
> Сделай так и вставляй его явно, а не получай при вставке
> тригером.
id-к получается через GeneratorField и Gen_ID в InsertSQL.
> Это нормальное решение для любой SQL-технологии
Почему для того что-бы вставить запись в датасет дочерней таблицы, приходится перчитывать родительскую? Нелогично...
Sergey13 (2005-09-20 09:35:00) [9]2[26] Девушка © (19.09.05 20:34)
Я тебе еще в [7] писал
>2.Получать ИДшник родителя можно (и лучше) ДО вставки.
Сделай так и вставляй его явно, а не получай при вставке тригером.
msguns (2005-09-20 09:16:00) [10]Это нормальное решение для любой SQL-технологии
Refresh не перечитывает записи с сервера
Девушка (2005-09-19 20:34:00) [11]Но это - плохое решение т.к. приходится потом опять запись позиционировать. :(
Девушка (2005-09-19 20:11:00) [12]Опытным путем выяснилось, что если в AfterPost кроме коммита родительский датасет сначала закрыть потом открыть (простой рефреш почему-то не сработал) то указанная ошибка не возникает.
Девушка (2005-09-19 20:07:00) [13]Что-то не получается...
Итак в родительском датасете в AfterPost стоит
transaction.CommitRetaining;
Добавляем новую запись в родительский датасет. Говорим post. Новая запись появилась в выпадающем списке DBGridEH дочернего датасета (т.к. lookup поле). Выбираем в этом выпадающем списке ту новую родительскую запись. При попытке post-ть получаем ошибку внешнего ключа.
Что нужно сделать что-бы внешний ключ "увидел" новую запись в родительской таблице?
Оба датасета завязаны на одну транзакцию.
Параметры транзакции
read_committed
rec_version
nowait
Sergey13 (2005-09-19 16:51:00) [14]2 [22] msguns © (19.09.05 16:47)
Если через TIBDataset делать, то вроде должна встать куда надо.
msguns (2005-09-19 16:47:00) [15]>Девушка © (19.09.05 16:42) [20]
>Этого достаточно ? :)
Нет, если Вы хотите, чтобы добавленная (измененная) запись встала на "свое" место в гриде (в порядке сортировки).
Да, если Вы хотите, чтобы добавленную (измененную) запись увидели другие пользователи (при переоткрытии своих запросов разумеется)
Sergey13 (2005-09-19 16:43:00) [16]2[20] Девушка © (19.09.05 16:42)
>Этого достаточно ? :)
Для чего?
Девушка (2005-09-19 16:42:00) [17]
> Вместо commit используй CommitRetaining.
Этого достаточно ? :)
Sergey13 (2005-09-19 14:51:00) [18]2[16] Девушка © (19.09.05 14:18)
Вместо commit используй CommitRetaining. Просто Commit закрывает транзакцию.
Девушка (2005-09-19 14:47:00) [19]
> msguns © (19.09.05 14:29) [17]
Не совсем понятно, когда dataset сам откатывает/подтверждает транзакции.
А по поводу TIBQuery+TIBSQL дык это уже делалось... хочется новое освоить :)
msguns (2005-09-19 14:29:00) [20]А внимательно и вдумчивопрочитать 2-й абзац [15] ?