| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Базы данных и репортинг > Транзакции в справочниках и документах |
| Автор: Delphist 21.12.2010, 21:32 |
| Есть справочник(и) (не модальная форма, транзакция DictTran) работа с транзакцией происходит по принципу AutoCoomit := False. Транзакция Commit'иться только в том случае, если пользователь нажимает на панели инструментов дискету (сохранение, при чем есть кнопка отката до последнего сохранения) или при закрытии справочника подтверждает сохранения данных. Есть документ(ы) (при создании документа форма открывается в модальном режиме, транзакция DocTran) - данные которого формируются из справочников, путем их вызовов и выбора из него необходимых элементов, справочник при этом открывается в модальном режиме. Если справочник открывается для выбора из него элементов и вставки их в документ, то он принудительно выставлялся в режиме ReadOnly (только чтение). В результате если пользователю, во время создания документа, вдруг приспичило в этом справочники, что либо отредактировать или вставить новые записи, ему приходилось закрывать документ и открывать справочник для редактирования. В принципе меня это технология прикалывала, она обязывала пользователя сначала сформировать в справочнике все необходимые данные, а уж потом юзать их при формировании документов. Но как оказалось на практике - пользователя это сильно раздражает, в связи с этим сейчас хочу переделать и хочу посоветоваться как лучше сделать: 1) при создании документа, открывать справочники в режиме AutoCommit := True, геморой в плане ошибок минимален (даже в сетевом режиме, когда БД одна, а пользователей много). Но есть и косяк - придется спрятать кнопку отката изменения (DictTran.RollbackRetaining), т.к. она уже в данном случае будет бесполезна 2) при создании документа, открывать справочники в режиме AutoCommit := False, но в случае, если пользователь выбрал компоненты из справочника и нажал кнопку ОК, перед вставкой их в документ и закрытием справочника происходит DictTran.CommitRetaining. Есть проблема для сетевого варианта, т.к. один и тот же справочник откроют разные юзеры в итоге приведет к блокировке транзакций. Какой лучше способ выбрать? Как правило как делают в таких случаях. P.S. Ща юзал одну прогу складскую в ней реализовано по первому принципу. В своей проге использую СУБД Firebird 2.0. |
| Автор: Deniz 22.12.2010, 06:18 |
| Delphist, основное требование, это: 1. Читающая транзакция может длиться очень долго, это не нагружает сервер и rollback не нужен. 2. Пишущая транзакция должна быть как можно короче с последующим Commit. В твоем случае 1 вариант не удобен пользователю(плюс при обрыве соединения неподтвержденные данные могут потеряться), а во втором есть проблема с длинной пишущей транзакцией для справочников. Решение может быть такое: добавил пользователь в справочник запись и тут же Commit. |
| Автор: Delphist 22.12.2010, 10:34 |
А если пользователю захочется сделать отмену добавленных записей? |
| Автор: superVad 22.12.2010, 11:03 | ||
Думать надо перед тем как подтверждать изменения. |
| Автор: Delphist 22.12.2010, 12:05 |
Так ведь Deniz предлагал такое - "Решение может быть такое: добавил пользователь в справочник запись и тут же Commit" Т.е. пользователь добавляет запись и она тут же Commit'иться т.е. думай не думай, а она уже закомитилась. И ещеDeniz предложил делать сразу Commit только для Insert'a или же для Update тоже сразу делать Commit? |
| Автор: superVad 22.12.2010, 14:09 | ||
Delphist, такой вопрос назрел - у тебя справочники редактируются прямо в гриде или есть отдельная форма для редактирования записи?
Я так понимаю: Делаешь Append или Update. Пишешь все, что надо в поля и делаешь Post. Если у тебя стоит AutoCommit, то по Post все комитится, иначе надо сделать Commit (в случае ошибки Rollback). Если отмена то вместо Post - Cancel. т.е. я к тому, что сразу добавить и закомитить не получится - надо еще какие то данные ввести. |
| Автор: Delphist 22.12.2010, 14:47 | ||
Если говорить о справочниках, то в основном все прямо в гриде, но есть и когда открывается модальная форма для редактирования записи. |
| Автор: cat512 22.12.2010, 15:25 |
| Существуют две стратегии работы с серверами бд: длинные и короткие транзакции. Каждые имеют свои плюсы минусы. Короткие транзакции подразумевают последующий commit после модификации данных, длинные подразумевают выполнение каких либо действий (выполнение какой-то бизнес логики), с возможным использованием операторов savepoint и др., для сохранения промежуточных результатов. Длинные транзакции, сложнее в реализации. Поэтому, народ правильно тебе советует: используй короткие транзакции; интерфейс должен быть единообразным (если модифицируешь данные через модальные формы, то так должно быть везде), а не так как у тебя, в одном месте через грид, в другом через формы; Пользователя, нельзя нагружать не существенными деталями. Кнопка откатить изменения, нахрен не нужна. Достаточны две или три кнопки( в случае длинными транзакциями) - ок, отмена, и применить. Как правило с учётными системами работают серьёзные люди, понимающие, что они делают. Ну а в случае если пользователь ошибся, то как правило в форме просмотра данных, всегда есть кнопки добавить, редактировать, удалить |
| Автор: Delphist 22.12.2010, 17:28 | ||
Ну тогда сразу поставить AutoCommit = True и все.
Модальная форма вызывается всего лишь в одном справочнике (пришлось так сделать из-за сложности справочника), а в 15 других редактируются напрямую в гриде. И вы хотите сказать, что в 15 случаях я должен был лепить модальные формы для элементарных справочников, если пользователю проще редактировать сразу в гриде. |
| Автор: superVad 22.12.2010, 18:29 |
Если редактировать из формы, то, наверное, да. А если грид, то надо быть точно уверенным когда он (Commit) сработает. Насколько я понимаю, то при переходе на другую запись. (А если запись только одна?) Может быть, что лучше самому это контролировать. |
| Автор: cat512 22.12.2010, 19:42 |
| Да, как правило в серьёзных поделках, можификация делается через модальные формы |
| Автор: Deniz 23.12.2010, 06:56 | ||
Пользователь добавил/отредактировал несколько записей, пошел покурить, пришел и отменил нафиг все изменения. Так что ли? А, какого, извиняюсь, он вообще туда что-то вносил? Это раз, а два, это в больших системах за справочники отвечает 1 чел (или группа), т.е. пока в справочнике нет записи, никто не может что-то добавить. Есть тут и плюсы и минусы. Но самый большой минус для изменения справочников "обычными" пользователями это: Москва Москвa Найди отличия? Для СУБД это две разные записи, потому как в одном "а" русская а в другом английская. Это общий пример, есть и другие варианты дублирования данных в справочниках. Если пользователь не нашел (или не захотел найти) запись, он добавит дубль. В общем тема большая. |
| Автор: Delphist 23.12.2010, 11:18 | ||
Понятно, что длинные пишущие транзакции это очень плохо. У меня как правило данные редактируются на прямую в гриде, как быть в этом случае. Если оставлять как есть, то так и останутся длинные пишущие транзакции, что не есть гуд, если сделать все AutoCommit'e это хорошо, но если случайно (этот фактор часто присутствуют у юзеров) он удалит, то прощай данные, в этом и есть большой минус. Можно сделать автосохранение (авто коммит, например каждый 5 мин), но не знаю правильно ли это? В общем жду совета. P.S. Да, хочу добавить, что использовать нормально CashedUpdates сейчас нет возможности |
| Автор: Deniz 23.12.2010, 12:06 | ||
Если посмотреть на этот вопрос с другой стороны, то пользователь может так же легко удалить и сохранить, так что автокоммит здесь не сильно проигрывает. Добавлено через 7 минут и 40 секунд Если дальше развить мысль, то сейчас у тебя пользователь для удаления делает: 1. Нажимает на кнопку "Удалить". 2. Получает запрос с подтверждением "Действительно удалить?" 3. Подтверждает. 4. Сохраняет изменения. Для автокоммита не будет пункта 4, имхо и первых 3-х достаточно. При отложенном сохранении удаленных записей есть момент, когда: 1. Пользователь 1 удалил запись но не сохранил. 2. Пользователь 1 добавил несколько других записей. 3. Пользователь 2 добавил запись со ссылкой(FK) на удаленную запись. 4. Пользователь 1 пытается сохранить изменения и получает Exception. 5. Пользователь 1 делает откат всех изменений, в т.ч. и результат работы п.2 За такие вещи можно и по лампадке схлопотать от пользователя 1. |
| Автор: Delphist 23.12.2010, 12:19 |
А мож все же автосохранение сделать? |
| Автор: Deniz 23.12.2010, 13:26 |
| решать тебе, но прочти еще раз мой последний пост про отложенное автосохранение (5 мин хватит для такой ситуации). |
| Автор: Delphist 23.12.2010, 14:52 | ||
Не совсем так, а будет вот так, я тока что проверил: 1. Пользователь 1 удалил запись но не сохранил. 2. Пользователь 1 добавил несколько других записей. 3. Пользователь 2 добавил запись со ссылкой(FK) на удаленную запись. Пользователю 2 выдастся сообщение нельзя добавить запись т.к. есть не подтвержденные данные или другой пользователь сети редактирует данную запись Firebird 2.0 автоматом в подобных ситуациях генерит сообщение содержащее фразу wait transaction вот ее я и проверяю и выдаю понятное сообщение |
| Автор: Deniz 23.12.2010, 15:25 |
| какие параметры транзакции? понятное кому? Пользователю 2? Ему надо срочно добавить запись, а он не может, потому как пользователь 1 ушел на обед с оставленной блокировкой. И создать новую запись(такую же) в справочнике пользователь 2 тоже не сможет, потому как уникальный индекс. Вот и начинается веселуха. |
| Автор: Delphist 23.12.2010, 17:12 | ||||
Да
пользователь 2 создать новую запись сможет, он не сможет всего лишь менять (редактировать, удалять) нашу проблемную запись, а также работать с объектами связанные с этой записью по Foreign Key |