![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Транзакция как бы глючит [D5, D7, MSSQL]
Fishka © (2004-04-09 10:25:00)Имеется запрос типа (ADOQuery, ADOConnection используется):
begin transaction T1;
declare ....
insert into A1 ....
if @@Error<>0 begin .... GOTO ERR_TR end
insert into A2 ....
if @@Error<>0 begin .... GOTO ERR_TR end
insert into A3 ....
...........................
if @@Error<>0 begin .... GOTO ERR_TR end
COMMIT TRANSACTION T1;');
ERR_TR: begin IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION T1;
BEGIN TRANSACTION T2;
update ....
COMMIT TRANSACTION T2;
end;
На форме есть AdoDataSet, поле которого отображается в DBRichEdit. Если два оператора случайно редактируют одновременно одну и ту же запись (DBRichEdit), то для второго оператора при попытке обработать эту запись (т.е. нажать кнопку, где идет приведенный выше запрос) выдается сообщение типа "запись была уже изменена" и далее невозможно даже уйти с данной записи, можно только закрыть форму. И при в таблицу А2 вносится запись, хотя в таблицу А1 запись не добавляется. И соответственно, нарушается целостность базы.
Вопрос: как избежать такой ситуации? Может быть, неверно установлены свойства используемых компонентов?
Fishka (2004-04-09 12:22:00) [21]В TRANSACTION T2 есть Update, но он тут ни при чем, а в TRANSACTION T1 нет Update вообще.
В DBRichEdit отображается значение поля, в котором текст, который по определенным правилам нужно разнести по таблицам.
После того, как в DBRichEdit было отредактировано некоторое поле и нажата кнопка, происходит ADOQuery.Cancel или .Post в зависимости от ответа оператора и далее идет INSERT, описанный выше.
Nikolay M. (2004-04-09 12:16:00) [22]
> Я бы сказал, что это ("транзакционность туда"), подход в
> корне неверный, не зависимо от типа SQL сервера...
Аргументы - ? Было бы интересно их услышать в зависимости от типа клиента - тонкий или для клиент-сервера. If you don`t mind, sir...
Nikolay M. (2004-04-09 12:13:00) [23]
> Updateнет вообще.
> BEGIN TRANSACTION T2;
> update....
> COMMIT TRANSACTION T2;
А это тогда что?
И как сочетается "нажатие на кнопку" (как я понимаю, ручной апдейт полей) и использование DB-aware компонент? Что происходит с ADOQuery после того, как в DBRichEdit было отредактировано некоторое поле и нажата кнопка? ADOQuery.Cancel? .Post?
Johnmen (2004-04-09 12:11:00) [24]>Delirium © (09.04.04 11:07) [6]
>...заложить всю транзакционность туда. Это более системный и
>грамотный подход вообще ...
"Вообще" - это для MSSQL ?
Я бы сказал, что это ("транзакционность туда"), подход в корне неверный, не зависимо от типа SQL сервера...
Fishka (2004-04-09 12:02:00) [25]Телепатировать не надо.
При нажатии на кнопку сначала удаляется запись из всех таблиц (запрос DELETE from A1 where ....). Затем при нажатии на кнопку идет приведенный выше запрос с многими INSERT-ами. Update нет вообще.
Да, меня волнует проблема работы с транзакциями на клиенте
и с использованием ADO.
Nikolay M. (2004-04-09 11:40:00) [26]
> обламывается, потом как в поле SomeField
...потому как в поле SomeField...
Nikolay M. (2004-04-09 11:39:00) [27]
> автора волновала проблема работы с транзакциями на клиенте
> и с использованием ADO.
Ну да, автор сделал, а нам - телепатировать :)
Хотя бы скажи, в какой момент этот запрос запускается :)
Я подозреваю, что он у тебя меняет значение некоторых ключевых полей, по которым идет апдейт и когда второй оператор пытается запостить данные запросом вроде
UPDATE tablename SET RichEditField = 'bla-bla' WHERE SomeField = XXX
он обламывается, потом как в поле SomeField значение XXX потерлось первым оператором на какое-нибудь YYY.
bushmen (2004-04-09 11:29:00) [28]Да, а end я не увидел. Старею :))
Fishka (2004-04-09 11:12:00) [29]Это кусок кода. Код полностью предполагает вставку в более чем 20 таблиц. Конструкция "if ... begin" написана верно. В день обрабатывается более 200 записей, и если операторы не встречаются на одной записи, то все нормально. Так что описанная выше ситуация бывает редко, но бывает.
Не понимаю, какое отношение имеет текст запроса, ведь он работает верно.
Delirium (2004-04-09 11:07:00) [30]"А я бы наоборот с клиента все транзакции убрал" - это было бы самое лучшее решение, описать бизнес-правила в виде хранимых процедур и заложить всю транзакционность туда. Это более системный и грамотный подход вообще, но ведь автора волновала проблема работы с транзакциями на клиенте и с использованием ADO.
Nikolay M. (2004-04-09 11:03:00) [31]
> делаешь ошибку в том, что не используешь механизм обработки
> транзакций самих ADO. У TADOConnection есть методы вызова,
> применения и отката транзакций, именно ими в купе с try
> except и надо пользоваться, чтобы ADO "понимали" что ты
> делаешь.
А я бы наоборот с клиента все транзакции убрал и реализовал их разруливание в хранимых.
Delirium (2004-04-09 11:01:00) [32]С точки зрения MSSQL всё работает правильно, но ты делаешь ошибку в том, что не используешь механизм обработки транзакций самих ADO. У TADOConnection есть методы вызова, применения и отката транзакций, именно ими в купе с try except и надо пользоваться, чтобы ADO "понимали" что ты делаешь.
Nikolay M. (2004-04-09 10:58:00) [33]
> "if ... begin" не будет работать без "end".
Как раз у "if ... begin" end есть, а вот у "begin ... if" - нет.
bushmen (2004-04-09 10:40:00) [34]Что-то у тебя кривовато написано. Конструкция "if ... begin"
не будет работать без "end". Либо пиши код полностью, либо вряд ли кто-то поймет, что ты написал
Nikolay M. (2004-04-09 10:38:00) [35]Имхо, не зная, какие именно данные редактируются, что конкретно постится, какие ключевые поля в каких таблицах, по вышеприведенному куску трудно что-то сказать.
ПолтерГейтс.