13.06.2008, 12:31 | #1 |
Участник
|
Foreign Key в Ax
Вероятно для большинства нижеизложенное не представляет интереса, но для начинающих, как я, это не так. Речь идет о том, как правильно сделать Foreign Key в MS DAX 4.0.
Хочу сделать пару таблиц master-detail. Для этого в Ах 4.0 делаю следующее: 1.Создаю EDT TestId. 2.Создаю таблицы TestMaster и TestDetail. В каждую из них кидаю TestId и Descripnion. 3.Создаю для таблицы TestMaster уникальный индекс TestIdx по полю TestId. Делаю его PrimaryIndex для этой таблицы. 4.Для таблицы TestDetail делаю не уникальный индекс по полю TestId. 5.В EDT TestId делаю relation TestId == TestMaster.TestId 6.В свойствах полей TestId в обеих таблицах ставлю Mandatory = Yes. 7.Для таблицы TestMaster делаю DeleteAction = Restricted по отношению к таблице TestDetail. Вроде бы все. Можно смотреть результат . Открываю Обозреватель таблиц для TestMaster и TestDetail. Пытаюсь вставить значение в TestDetail. Не получается . Хорошо . Вставляю пару строк в TestMaster (1 и 2). Вставляю пару строк в TestDetail для каждого значения из Master. Пытаюсь удалить из TestMaster. Не получается . Хорошо . Удаляю из TestDetail и снова пытаюсь удалить из TestMaster. Получается . Захожу на TestMaster и пытаюсь поменять TestId с 2 на 3. Получается . Ничего себе, строки в TestDetail стали сиротами! Отпив и бутылочки корвалола продолжаю тестировать. Создаю job такого содержания: Код: static void TestJobMD(Args _args) { TestDetail testDetail; ; ttsbegin; TestDetail.TestId = "100"; TestDetail.Description = "Test 100"; if (TestDetail.validateWrite()) TestDetail.insert(); ttscommit; } Допиваю остатки корвалола продолжаю. Создаю еще job: Код: static void TestDeleteMD(Args _args) { TestMaster testMaster; ; ttsbegin; select forupdate testMaster where testMaster.TestId == "2"; if ( testMaster.validateDelete()) testMaster.delete(); ttscommit; } Запускаю. Не проходит. Ну хоть тут Слава Богу. А теперь вопрос к знатокам. Я что-то не так сделал? Как человек, долго работавший с Oracle добавлю. Там (да и в MS SQL) таких проблем просто нет! Пару строк в скрипте создания таблиц.(Primary Key + Foreign Key) и вы получаете надежную ссылочную целостность, выдерживающую прямое попадание любой ядерной бомбы, запущенной умелой рукой пользователя . А в Ах что получается: спасение утопающих - дело рук самих утопающих? Т.е. программист должен сам все проверять? Еще раз повторю. Может я что-то не так сделал? Тогда готов посыпать голову пеплом. |
|
13.06.2008, 12:58 | #2 |
Участник
|
У Вас каждый пользователь имеет доступ к обозревателю таблиц? Обозреватель - инструмент "хирурга", а не простого пользователя. У Вас все пользователи Oracle имели права администратора?
Кроме того, нужно было хотя бы настроить Relation таблицы Detail на Master по ключевому полю со свойством Validate = Yes, а лучше сделать это в EDT. P.S. Всё описанное подробно рассматривается на тренингах по разработке и кратко описано в документации "Справка разработчика". |
|
13.06.2008, 13:30 | #3 |
Участник
|
Цитата:
Цитата:
А в EDT свойства Validate нет, это на таблицах. Кстати, кто-нибудь может объяснить, что означает отношение CustTrans.AccountNum == CustTrans.AccountNum Цитата:
Вообще, на мой взгляд самая неприятная ситуация - это то, что таблица-detail может заполняться автоматически в коде и программист может ошибиться (все мы люди), причем не грубо, а только в некоторых специфических ситуациях могут появиться сироты, причем система шума не поднимет, и выяснится это нескоро и починить будет непросто. |
|
13.06.2008, 14:39 | #4 |
Участник
|
Цитата:
Более подробно могут разъяснить наставники или на тренингах узнать. Но хотя бы этот документ обязательно нужно прочесть, чтобы понимать принципы разработки в Аксапте. Последний раз редактировалось Михаил Андреев; 13.06.2008 в 14:48. |
|
13.06.2008, 15:20 | #5 |
Участник
|
Да, каюсь, не дочитал Хотя подозреваю, что мало кто его прочел от корки до корки, особенно начинающие. Читают то, что нужно сейчас. Если найдут
Вот за это большое спасибо. Счас буду разбираться. |
|
15.06.2008, 14:48 | #6 |
Member
|
Цитата:
Сообщение от SergeK
...
Делаю его PrimaryIndex для этой таблицы. ... Цитата:
Сообщение от SergeK
...
Захожу на TestMaster и пытаюсь поменять TestId с 2 на 3. Получается . Ничего себе, строки в TestDetail стали сиротами! ... select forupdate table where ... table.field = "new value"; table.renamePrimaryKey(); table.update();
__________________
С уважением, glibs® |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
16.06.2008, 11:04 | #7 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: glibs (1). |
16.06.2008, 11:40 | #8 |
Member
|
__________________
С уважением, glibs® |
|
17.06.2008, 12:54 | #9 |
Участник
|
Спасибо всем откликнувшимся!
К сожалению, подтверждаются самые худшие мои опасения . Т.е. поддержка ограничения внешний ключ весьма убогая. Может быть гуру Ах могут как то прокомментировать, почему не задействована эта возможность на уровне СУБД? Кстати в Best Practices for Table Relations написано следующее: Цитата:
The system guarantees that data entered in the database fulfills the specified relations.
И еще Я извиняюсь за назойливость, но тут написано, что это нужно сделать, если таблица имеет ключ. НО! Ничего не написано, почему это нужно сделать |
|
17.06.2008, 13:57 | #10 |
Участник
|
Цитата:
Похоже, что через несколько версий останется только одна СУБД. Только тогда, наверное, и можно будет говорить о необходимости поддержки всех возможностей СУБД. Цитата:
Ищите. Здесь правильный ответ давал EVGL: Это нужно для процедуры переименования ключей, если ядро видит неоднозначности. |
|
17.06.2008, 15:39 | #11 |
Участник
|
|
|
17.06.2008, 15:54 | #12 |
Участник
|
Это "фича" системы, я бы сказал, гибкость.
Если разработчик понимает, что делает, то все будет написано правильно. Но вдруг ему таки нужно запихнуть строки не ссылающиеся на что-то? К примеру, создать строки заказа, не привязанные к конкретному заказу (простой способ создать проводки, кстати, без добавления нового типа проводок) |
|
17.06.2008, 16:18 | #13 |
Участник
|
Согласен с kashperuk'ом.
Цитата:
Программисту дается такая возможность. Но ответственность за неправильное функционирование в этом случае лежит на нем, на программисте. |
|
17.06.2008, 16:33 | #14 |
Участник
|
Всем спасибо! Туман рассеялся
Отдельное спасибо EVGL за неоднократное объяснение, зачем нужны Self-Relations. Поскольку этот вопрос регулярно задают начинающие, считаю, что ему самое место в FAQ. |
|
17.06.2008, 16:49 | #15 |
Участник
|
Дай прямую ссылку на конкретный ответ - и думаю, добавят
|
|
17.06.2008, 17:06 | #16 |
Участник
|
Да, не вопрос!
Цитата:
Сообщение от EVGL
Сам поставил опыт: вы не поверите, но поля в индексе, который выбран как PrimaryIndex на таблице, действительно становятся членами первичного ключа в SQL!
Relations не при чем, а то, что написано в документации, относится к первичному ключу в понимании Аксапты, т.е. к полю, которое можно переименовывать. Именно для глобального переименования кодов справочников и нужны self-relatations. Цитата:
Сообщение от EVGL
Запуск BestPractice дает ответ на этот вопрос. Self-relation нужны для переименования первичных ключей.
Если расширенный тип не имеет такой ссылки, то BestPractice выдает соответствущее предупреждение и ждет, что ссылка будет создана на самой таблице. Однако в ряде таблиц (RAssetMoveHist, скорее всего, в их числе) первичного ключа либо нет, либо он состоит из нескольких полей. Тут попытка создать Self-relation ни к чему не приводит: BestPractice продолжает ошибочно выдавать все то же предупреждение. Есть и еще одна причина: в ряде случаев программист хочет, чтобы при вызове формы создалась динамическая ссылка с источником данных вызываеющего объекта. Пример: вызов проводок по ГК из плана счетов. А если вызывающая и вызываемая таблицы одинаковые? Если таблицу рабочих центров вызываем из формы рабочих центров и хотим видеть, как содержимое второй формы фильтруется по номеру из первой? Автоматически наложить правильный DynaLink на таблицу (особенно с первичным ключом из двух и более полей) в таком случае помогает Self-relation. |
|
Теги |
ax4.0 |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|