14.01.2005, 15:48 | #1 |
Участник
|
Проверка подчиненных записей
Уважаемые коллеги!
Такое дело... Форма. На форме два датасорса D1 и D2. D2.JoinSource = D1 D2.LinkType = Delayed Соотвественно два Grid: Grid1 - на D1 Grid2 - на D2 Создаем новую запись... Вопрос: как запретить сохранять запись, если в D2 нет ни одной соответствующей записи? Буду рад.. |
|
14.01.2005, 16:24 | #2 |
Moderator
|
Неправильная какая-то постановка задачи. Запись в D1 (родительская таблица) должна быть сохранена раньше, чем будут создаваться связанные с ней записи в дочерней таблице.
__________________
Андрей. |
|
14.01.2005, 16:51 | #3 |
экс-модератор
|
а вам зачем вообще?
|
|
14.01.2005, 16:54 | #4 |
Участник
|
Согласен, неправильная.
В том-то все и дело.. Неужели нет никакого способа? Ведь с точки зрения заказчика вполне понятное требование - "хочу, чтобы Запись Персона нельзя было сохранить, пока для нее не указан хотя бы один контактный Телефон и телефонов может быть несколько" C++ + SQL позволяют легко решить эту задачу через хранимые процедуры. И вообще, если обобщить, то задача сводится к "проверить данные на форме до попытки сохранить" |
|
14.01.2005, 17:21 | #5 |
экс-модератор
|
не, в аксапте строка всегда сохраняется при переходе фокуса из одного грида в другой.
можете, например, в методе close() формы удалять ненужные вам строки. |
|
14.01.2005, 17:26 | #6 |
Участник
|
Сделайте для Персоны некий статус, при выставлении которого персона становится доступна для выбора и прочего использования. А статус устанавливайте в коде, вызываемом по кнопке с формы. В этом коде и сделайте проверку на существование записей в подчиненной таблице.
|
|
14.01.2005, 17:51 | #7 |
Участник
|
2 maxsmirnov
Все бы хорошо, да только если закрыть Аксапту целиком (самый-самый главный крестик, например), то close() на форме не вызовется Соответственно... запись останется сохраненной без подчиненных. И еще минус с удалением - ном.серия нарушится. 2 Gad Т.е. ... э-э-э ... не совсем понял Про статус и проверку вроде понял, а вот про то, как это позволит избежать write() при переходе с D1 на D2 для внесения записи в D2 - не понял - ? |
|
14.01.2005, 17:56 | #8 |
Moderator
|
Цитата:
если
закрыть Аксапту целиком (самый-самый главный крестик, например), то close() на форме не вызовется А по поводу решения - можно попробовать использовать некий временный буфер (временную таблицу, список), редактируя его в отдельной форме, а при сохранении записи основной таблицы проверять заполненность этого буфера.
__________________
Андрей. |
|
14.01.2005, 17:57 | #9 |
Участник
|
2 lego_99
Никак не поможет. Я просто предлагаю слегка изменить постановку задачи и в местах использования Персоны ввести запрет на использование записей с неактивным статусом. От хранения записей без подчиненных это конечно не спасет. |
|
14.01.2005, 18:30 | #10 |
Участник
|
2 maxsmirnov
Виноват, был не прав. На SP2 при закрытии Аксапты close() будет вызываться. На SP1 - нет. 2 Dron AKA andy У, блин, везука. На AX3.0 SP1 этим похвастацца, как бы ни хотел, никак не могу Буфер - временная таблица то бишь? Если да, то ведь синхронизировать придется... с таблицей на сервере. Cравнить две таблицы - и обновить серверную до состояния временной? Хотя, с другой стороны, если открываем Персону, а у нее уже есть хотя бы один Телефон, то и временная таблица нам, по идее, не нужна.. Т.е. синхронизировать придется только в первый раз. А дальше - запретить удалять все записи (оставлять хотя бы одну). Есть ли способ малой кровью (читай "меньше кода") синхронизировать Временную Таблицу и Серверную? Может быть, как-нибудь Map можно прибить к этому делу или метод какой хитрый есть? Навскидку. 2 Gad Это поможет, но ведь "мест использования" может быть больше одного .. или больше десяти, например. Хотя в таком случае действительно будет все работать, особенно если отфильтровать записи в Персоне, так, чтобы не было видно тех, что без подчиненных. Мысль. _________________________________________ Метод с буфером кажется мне предпочтительнее. |
|
14.01.2005, 19:01 | #11 |
----------------
|
Может в персоне добавить обязательное поле "primary контакт"... а после сохранения автоматом вливать первую запись в контакты...
а, кстати при удалении всех контактов, персона должна грохнуться? |
|
14.01.2005, 20:15 | #12 |
Участник
|
2 Wamr
Если ввести Primary Contact, то это будет даже удобно. (Контакт же обязательно должен быть, почему бы первым Контактом и не быть Контактом в виде поля?) По-моему, это лучшая идея из всех. Понятно, как делать и много времени не займет. P.S.: Интересно, а реально ли реализовать механизм что-то типа наподобие - указал при init() главного датасорса без записей в каком / каких подчиненных датасорсе/ах нельзя сохранять главный и этот механизм бы все корректно делал ? Кажется реальным, но механизм должен быть универсальным и не зависеть от "формы" таблиц и кол-ва подчиненных датасорсов. Так, для разминки. |
|
14.01.2005, 22:34 | #13 |
Участник
|
Конечно реально - просто не надо подчинять датасоурсы друг другу по джойну, а пользоваться фильтрами (т.е. range-ами) инициализируемыми в active / linkActive.
Это даёт свободу дейтствий, но обязывает к хард-кодингу. В общем согласен что постановка задачи неправильная - подчинённая запись не может быть сохранёна в реляционной СУБД раньше мастер-записи. Не может и точка. Это идеологическая концепция которую можно обойти только отказом от реляционности - т.е. отказом от join-ов, т.е. см. выше. |
|
15.01.2005, 00:02 | #14 |
Участник
|
2 Alks
Ага. Убрать join и "косить" под них. Тут без hard-programming точно не обойтись. Хотя, если уж зашли в такие вещи, то дальше уж нам точно без программинга никак. Попробую, че получится - выложу. Как-нибудь. Цитата:
подчинённая запись не может быть сохранёна в реляционной СУБД раньше мастер-записи
Вопрос же в том, чтобы не сохранить подчиненный датасоурс раньше главного, а проверить подчиненный (и ... главный ... все что угодно), а потом сохранить. И то, что постановка неправильная, я тоже согласен. Сам не рад, слю-у-у-шай.. У-у-ффффф. Ща вааще серьезный вопрос задам.. Ж REM: Открыли по банке пива и приготовились открыть по второй. 2 All !!! действительно ли противоречит реляционности БД, например, такая вещь: А) проверить Контакты проверить Персоны сохранить Персоны сохранить Контакты и чем она "хуже", чем: Б) проверить Персоны сохранить Персоны проверить Контакты сохранить Контакты ? Т.е., я имею ввиду не сохранение подчиненной до того, как был сохранен главный датасоурс, а проверку датасоурсов до сохранения. Чем последовательность, которая сейчас есть в Аксапте, лучше последовательности, при которой бы все связанные датасоурсы сначала заполнялись (без write() при переходе от одного датасоурс к другому), потом проверялись, а потом бы в одной транзакции сохранялись? P.S.: Не особо люблю грить за всех , но Думаю, все (ну или многие) были бы благодарны, если бы вдруг в этой ветке появился пример, который бы показывал различия между А) и Б) Автору дельного примера, думаю, был бы большой respect. Ну и .. это.. тему можно было бы закрыть заодно на мажорной ноте.. (Либо я че-то недопонял хде-то и давайте все сначала ) |
|
16.01.2005, 07:45 | #15 |
Участник
|
Цитата:
Вопрос же в том, чтобы не сохранить подчиненный датасоурс раньше
главного, а проверить подчиненный (и ... главный ... все что угодно), а потом сохранить. Проверяйте содержимое подчинённого датасоурса из validateWrite подчиняющего, а не из его собственного validateWrite. (а в собственном validateWrite вообще ничего не делайте). Тут нужно определить: а) есть ли уже в базе хотя бы одна запись подчинённая master-записи б) если нет, то находятся ли в подчинённом датасоурсе данные которые форма намеревается сохранять в БД в) если находятся, то проверить заранее являются ли они корректными (потому как в дальнейшем возможно им будет отказано во внесении в БД например по причине дублирования уникального индекса) Тут вся сложность в последних двух пунктах - как проверить есть ли в datasource запись которую форма будет сохранять в БД я прямо сейчас не знаю, но способ этот просто обязан быть, т.к. самой форме тоже нужно как то определять этот момент. Ну и последний пункт думаю тоже не будет большой проблемой. |
|