AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 17.10.2018, 15:37   #1  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
642 / 347 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Паттерн Related Table
Решил немного порязмять свои писательские способности и черканул в блоге об использовании простенького паттерна.
Вот ссылка.
Говорится о том, как хорошо было бы стандартизовать табличные методы, возвращающие ссылки на связанные таблицы.
И да, если мы это будем использовать только локально, проку будет мало. Однако (не знаю, как там сейчас дела обстоят в D365) если Microsoft возьмет на вооружение, то это было бы очень существенно.

Вообще у кого какие мысли по данному паттерну? Интересно или бесполезно?
__________________
// no comments

Последний раз редактировалось dech; 17.10.2018 в 16:08.
За это сообщение автора поблагодарили: trud (2), wojzeh (1).
Старый 17.10.2018, 15:58   #2  
Ivanhoe is offline
Ivanhoe
Участник
Аватар для Ivanhoe
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
 
4,143 / 2155 (80) +++++++++
Регистрация: 29.09.2005
Адрес: Санкт-Петербург
Лучше в ссылку добавить https
__________________
Ivanhoe as is..
Старый 17.10.2018, 16:10   #3  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
642 / 347 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Цитата:
Сообщение от Ivanhoe Посмотреть сообщение
Лучше в ссылку добавить https
добавил
__________________
// no comments
Старый 17.10.2018, 16:59   #4  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
чем только люди в Омске не развлекаются!

теперь по делу.

1. не понял, где будем обсуждать - тут или там, где сама статья (по умолчанию буду тут)
2. "Пожалуй уже всем надоело каждый раз выискивать подходящий метод" - не в том дело, что надоело, а в том, что его иногда просто нет. это ж вопрос воспитания: добавил рилейшон - добавь метод!

3. если интересует настоящая расширяемость, когда код пишется один раз, а дальше хоть трава не расти, то вот мои reflections по этому поводу:

Название: tableManyRelations.png
Просмотров: 609

Размер: 152.6 Кб

X++:
static void wzhGetRelatedTableNames(Args _args)
{
    wblInExtCodeValueTable          wblInExtCodeValueTable;
    int                             mapId;
    TableName                       relatedTableName;
    TableId                         relatedTableId;
    Set                             tablesIdsSet    = new Set(Types::Integer);
    Set                             tablesNamesSet  = new Set(Types::String);
    TableId                         tableId         = tableName2id(tableStr(wblInExtCodeValueTable));
    Dictionary                      dictionary      = new Dictionary();
    SysDictTable                    dictTable       = dictionary.tableObject(tableId);
    DictRelation                    dictRelation    = new DictRelation(wblInExtCodeValueTable.TableId);
    int                             mapCnt          = dictTable.relationCnt();
    container                       ret ;            
    str                             relationName;
    //create a maps of literals for all tables from the table relations
    // so that we could get tables names based on their ids
    // and if any new relation will be added to multiple external codes table
    // it is present automatically in this view
    for (mapId=1; mapId <= mapCnt; mapId++)
    {
        // elaborate if any table present many times
        relationName        = dictTable.relation(mapId);
        dictRelation.loadNameRelation(relationName);
        if(dictRelation)
        {
            relatedTableId      = dictRelation.externTable();
            relatedTableName    = tableId2pname(relatedTableId);
            tablesIdsSet.add(relatedTableId);
            tablesNamesSet.add(relatedTableName);
            info(strFmt("Table %1 - %2", relatedTableId, relatedTableName));
        }
    }
        
    ret = [tablesIdsSet.pack(), tablesNamesSet.pack()];
}
а дальше там уже находи и открывай, чего хочется.

Название: relationsResult.png
Просмотров: 613

Размер: 97.5 Кб

я сделал через table map связь внешних кодов 1:N
__________________
Felix nihil admirari
За это сообщение автора поблагодарили: dech (5).
Старый 17.10.2018, 17:28   #5  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2922 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Есть ещё https://community.dynamics.com/ax/b/...ion-properties
За это сообщение автора поблагодарили: wojzeh (1), S.Kuskov (5), dech (3).
Старый 17.10.2018, 17:48   #6  
Raven Melancholic is offline
Raven Melancholic
Участник
Аватар для Raven Melancholic
Самостоятельные клиенты AX
Лучший по профессии 2015
 
2,158 / 1286 (47) ++++++++
Регистрация: 21.03.2005
Адрес: Москва-Петушки
Цитата:
Сообщение от belugin Посмотреть сообщение
Действительно, уже с DAX2012 появилась такая возможность, причем если не устраивает название по умолчанию, то можно задать свое. Более того, при помощи таких методов можно подсовывать уже найденное значение и при повторных доступах курсор не будет считываться из базы.
Старый 17.10.2018, 17:52   #7  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от belugin Посмотреть сообщение
а какие там "подводные камни" у этого подхода? там, в каментах, народ жалуется, дескать, что-то не так работает.

я как-то раз пользовался этой штукой, по-моему, когда создавал кучу связанных записей с помощью unitOfWork

и чтоб два раза не вставать: это только у меня не работает Set tableRelationsSet = DictTable.relations() ?
__________________
Felix nihil admirari
Старый 17.10.2018, 18:13   #8  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,273 / 3466 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от dech Посмотреть сообщение
Вообще у кого какие мысли по данному паттерну? Интересно или бесполезно?
Изначальная мысль интересная. Но я бы все-таки ее привязывал к релейшнам, как это сделано в AX2012 (ссылку дал belugin). Это более правильно на мой взгляд (и кстати в 2012 работает).
Но в D365:
1. Подход из AX2012 не работает (ну или я с этим не разобрался)
2. Принципиально реализован другой подход к разработке. В частности - чаще используются сложные запросы, вьюхи, готовые классы, инкапсулирующие внутри себя все потребности составления запросов.
3. Появились расширения, в результате которых код и релейшны одной таблицы могут быть разбросаны по многим расширениям и многим классам. Т.е. найти этот "related" метод будет весьма сложно. А порой и невозможно, если нет ссылок на модель, в которой он присутствует.

Поэтому я бы эту мысль классифицировал, как мысль, у которой нет хорошего решения по реализации. В 2009 и ранее - используется один подход, в 2012 - другой, а в D365 - третий.
__________________
Возможно сделать все. Вопрос времени
Старый 17.10.2018, 18:17   #9  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
его идея как раз в том, чтоб не привязываться к синтаксису (имени метода) при поиске связанной записи. вьюхи-шмухи тут ни при чём.
__________________
Felix nihil admirari
Старый 17.10.2018, 18:49   #10  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,273 / 3466 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от wojzeh Посмотреть сообщение
его идея как раз в том, чтоб не привязываться к синтаксису (имени метода) при поиске связанной записи. вьюхи-шмухи тут ни при чём.
Дело не в этом. В АХ2009 и ранее была потребность в переходе от курсора одной таблицы к другой. Например, от inventTrans к inventTable, от salesTable к CustTable и т.д.
В 2012 и далее многие таблицы "распилили", т.о., к примеру, чтобы перейти от inventTrans к custTable / vendTable нужно еще "прыгнуть" в inventTransOrigin и оттуда - в DirPartyTable. Но поскольку исходная задача не изменилась (т.е. сама inventTransOrigin никому особо не нужна - нужен в конечном счете только клиент), то и потребности в переходе к отдельно взятой промежуточной таблице, которая появилась исключительно по техническим причинам - нет. Т.е. теперь, если захочется перейти от inventTrans к custTable - нужно будет написать некий кверик с джойнами из нескольких таблиц (=вьюха), либо ... найти комбинацию штатных методов, которая в конечном счете приведет к требуемому результату.

Про LedgerTrans я уж вообще молчу - там 5 таблиц целых . А для тех же финаналитик сделаны готовые классы, которые успешно работают и которые вполне можно применять, вообще не заморачиваясь на внутреннюю реализацию структуры финаналитик и не делая ни одного джойна (а джойны, если их делать - там тоже получатся многоэтажные).

Поэтому и потребность в переходе от одной таблице к другой одним методом, как это было раньше через find по сути - сильно уменьшилась и осталась только для менее востребованных таблиц
__________________
Возможно сделать все. Вопрос времени
Старый 17.10.2018, 19:10   #11  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
похоже, вы с ним о разных вещах говорите:

"табличные методы, возвращающие ссылки на связанные таблицы" - то есть, как получить то, что у нас есть.

в приведённой тобой таблице inventTrans нет таких связанных таблиц, как CustTable, VendTable, но есть, например Currency и ProjTable.

то есть, как добраться до того, чего у нас тут на таблице нет.
__________________
Felix nihil admirari
Старый 17.10.2018, 19:36   #12  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,273 / 3466 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от wojzeh Посмотреть сообщение
похоже, вы с ним о разных вещах говорите:
Не совсем. Топикстартер предлагает решение некой задачи и предлагает его обсудить. Я же говорю о том, что в силу изменившейся архитектуры системы в последних версиях системы исходная задача становится маловостребованной и поэтому предлагаемое решение имеет ограничение по своему применению
__________________
Возможно сделать все. Вопрос времени
Старый 17.10.2018, 19:39   #13  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
672 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
приведи пример, где предлагаемое им решение не сработает в связи с "изменившейся архитектурой".

ты, кстати говоря, видел, как у меня открываются формы по ссылке на разные таблицы?

__________________
Felix nihil admirari
Старый 18.10.2018, 00:11   #14  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,273 / 3466 (122) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от wojzeh Посмотреть сообщение
приведи пример, где предлагаемое им решение не сработает в связи с "изменившейся архитектурой".
Хорошо, хорошо - умолкаю. Вид с одной стороны не объективен Конечно все будет работать . Собственно я и не говорил, что работать не будет

Цитата:
Сообщение от wojzeh Посмотреть сообщение
ты, кстати говоря, видел, как у меня открываются формы по ссылке на разные таблицы?
Нет. Ну да - в этом случае тот вариант метода конечно незаменим.
__________________
Возможно сделать все. Вопрос времени
Старый 18.10.2018, 07:30   #15  
trud is offline
trud
Участник
Лучший по профессии 2017
 
1,038 / 1629 (57) ++++++++
Регистрация: 07.06.2003
Записей в блоге: 1
Цитата:
Сообщение от dech Посмотреть сообщение
Вообще у кого какие мысли по данному паттерну? Интересно или бесполезно?
я бы такое использовать не стал.
т.е. первое - у вас не будет перекрестных ссылок, они все будут на один метод. этим мне также не нравится подход АХ2012 - его использую только если надо быстро написать одноразовый код.
второе - банально неудобно - т.е. мне надо вызвать .inventTable(), я набираю .inv.. и смотрю - есть ли вообще такой метод.
В вашем случае будет метод related, который мне надо будет все время открывать и проверять - есть ли там реализация для InventTable
третье - как вы уже сами заметили в общем случае связей может быть несколько. т.е. будет .inventTableFrom() .inventTableTo(), и это будет сразу видно при написании кода
PS:
Но саму идею статей и шаблонов искренне поддерживаю, за это спасибо

Последний раз редактировалось trud; 18.10.2018 в 07:36.
Старый 18.10.2018, 08:54   #16  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2922 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от wojzeh Посмотреть сообщение
а какие там "подводные камни" у этого подхода?
У меня сложилось впечатление, что это не всегда работает. Но следует учесть что мы часто работаем на всяких промежуточных версиях платформы, так что оно может быть нерелевантно.
Старый 18.10.2018, 09:00   #17  
belugin is offline
belugin
Участник
Аватар для belugin
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,622 / 2922 (107) +++++++++
Регистрация: 16.01.2004
Записей в блоге: 5
Цитата:
Сообщение от trud Посмотреть сообщение
я бы такое использовать не стал.
т.е. первое - у вас не будет перекрестных ссылок, они все будут на один метод. этим мне также не нравится подход АХ2012 - его использую только если надо быстро написать одноразовый код.
Я присодиняюсь. Хочу еще добавить, что:
  • Аргумент - имя таблицы недостаточен для того, чтобы найти запись. Может быть несколько связей на одну таблицы. Надо имя связи,
  • С точки зрения пользователя case ничем не лучше чем naming convention (типа findInventTable) - этим исправляется тот недостаток что нет intellisense и перекрестных ссылок.
Возможно, я бы решил такую проблему кодогенерацией, а не рантайм кодом (по всем ссылкам явным и неявным сгенерировать find<ИмяСсылки>)
Старый 18.10.2018, 15:04   #18  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
642 / 347 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Спасибо за развернутые ответы.
И да, данное мое решение ориентировано в первую очередь на AX 4, 5 версий. 2012 я уже года 3 как в глаза не видел. Засиделся так сказать на клиенте.)))
Релейшены конечно да - это тема. Однако я хотел сделать более просто. Вообще интересный код с рефлексией у Wojzeh. Только если нет relation'а, то нет и результата. А вот если по свойству включаем создание подобных методов, это уже какой-то сахарный костыль...)) Все-таки я за один единый метод, нежели 10 разных.
__________________
// no comments
Старый 21.10.2018, 01:47   #19  
Владимир Максимов is offline
Владимир Максимов
Участник
КОРУС Консалтинг
 
1,651 / 1158 (42) ++++++++
Регистрация: 13.01.2004
Записей в блоге: 3
Программисты такие программисты

- Вы знаете, мне кажется, что натягивать сову на глобус несколько неудобно. Давайте обсудим вариант запихивания глобуса в сову!
- Оно, конечно, хорошо, но у Вашего метода есть некоторые недостатки...



Есть текущая запись таблицы SalesLine. Вам надо найти связанную с ней запись SalesTable. Что первое в голову приходит?

X++:
salesTable = SalesTable::find(salesLine.SalesId);

Вот ЭТО и есть "генеральная линия партии" и логика работы с таблицами. Собственно Best Practices настойчиво рекомендует создавать метод find() на всех новых таблицах. Куда уж универсальнее-то?

Т.е. сама постановка задачи, мягко говоря, идет в разрез с логикой работы с Axapta. Методы на таблицах типа salesLine.SalesTable() создаются либо от непонимания (привычка из другой среды программирования), либо из-за особенностей конкретного обращения к конкретной таблицы (сложность алгоритма, дополнительное поле и т.п.)

Иными словами, такой способ организации поиска записи таблицы-родителя в среде Axapta сам по себе является исключением. Нетипичным обращением. Ну, и зачем пытаться вывести некое универсальное решения для исключений?

PS: На всякий случай уточню. Это правило для младших версий Axapta (с которыми автор и работает). Для старших - в настоящее время еще нет устоявшихся правил. Все меняется на лету. Даже в рамках одной версии
__________________
- Может, я как-то неправильно живу?!
- Отчего же? Правильно. Только зря...
Старый 22.10.2018, 09:44   #20  
dech is offline
dech
Участник
Аватар для dech
Самостоятельные клиенты AX
 
642 / 347 (13) ++++++
Регистрация: 25.06.2009
Адрес: Омск
Записей в блоге: 3
Цитата:
Сообщение от Владимир Максимов Посмотреть сообщение
Т.е. сама постановка задачи, мягко говоря, идет в разрез с логикой работы с Axapta. Методы на таблицах типа salesLine.SalesTable() создаются либо от непонимания (привычка из другой среды программирования), либо из-за особенностей конкретного обращения к конкретной таблицы (сложность алгоритма, дополнительное поле и т.п.)

Иными словами, такой способ организации поиска записи таблицы-родителя в среде Axapta сам по себе является исключением. Нетипичным обращением. Ну, и зачем пытаться вывести некое универсальное решения для исключений?

PS: На всякий случай уточню. Это правило для младших версий Axapta (с которыми автор и работает). Для старших - в настоящее время еще нет устоявшихся правил. Все меняется на лету. Даже в рамках одной версии
Вы абсолютно не правы. Судя по вашему мнению, разработчики MS совершенно не понимают, что пишут... Подобные методы есть и в последних версиях Аксапты, будь то 2012 или D365. Вы можете игнорировать подобный подход и топорно вызывать find() по старинке. Однако оптимальный код должен быть простым и компактным. Т.е. нормальный разработчик старается вызывать методы либо вообще без параметров, либо с минимальным их набором.
Плюс вашего подхода - используем чисто find() и не паримся с доп. методами типа salesLine(). Минус же в том, что вам нужно помнить внешний ключ (SalesId-то все знают, а если рассматривать более редкую таблицу, а если ключ составной?). Плюс моего подхода - такая же унификация по имени метода как и find, но также метод может вернуть любую таблицу, которая там прописана. А find - не может. Другой плюс - нам не нужен ключ к таблице, нам нужна сама таблица.
__________________
// no comments
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
david_kidder: ReferenceTable & Table References on EDT Blog bot DAX Blogs 0 05.09.2013 15:11
ax-erp: ReferenceTable & Table References on EDT Blog bot DAX Blogs 0 18.12.2012 02:11
PatrickChua: Temporary table Blog bot DAX Blogs 0 04.05.2009 14:05
jerry-dynamics: How can you make sure that the end user can not delete a record in one table if there are related records in another table? Blog bot DAX Blogs 0 16.06.2007 11:20
PatrickChua: Temporary table Blog bot DAX Blogs 0 28.10.2006 18:14
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 16:05.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.