11.01.2012, 23:13 | #1 |
Administrator
|
AX 2012 Наследование таблиц. Краткое описание механизма
Добрый день! Пришлось тут в рамках подготовки к курсу 80299 What's New -Technical in Microsoft Dynamics AX 2012 for Development поисследовать AX 2012, и, поискав достаточно скудную информацию о наследовании таблиц (на русском – так вообще отсутствующую) – решил поисследовать самостоятельно – что же это за технология изнутри. Описанное ниже является исключительно моим мнением, не претендующим на истину в последней инстанции, и не являющееся заменой документации по данной функциональности.
Предназначение Данная технология хорошо предназначена для разделения одной большой таблицы по полям на несколько маленьких (подразумевается вертикальное разделение – когда часть полей из большой таблицы «уезжает» в другую). Хорошим примером ситуации, когда наследование таблиц имеет смысл применять – являются таблицы InventJournalTrans / LedgerJournalTrans – строки журналов, в которых имеются поля, специфичные только для журналов определенного типа, а для остальных данных – они являются ненужными. Примером здесь могут являться поля, относящиеся к основным средствам (для LedgerJournalTrans) или поля, относящиеся к инвентаризации (для InventJournalTrans). Принцип построения структуры таблиц в СУБД Наследование таблиц, как технология – реализована в АХ 2012 по принципу абстрагирования программиста от СУБД (как в 1С), когда разработчик задает системе некоторые принципы, а ядро реализует эти принципы в СУБД и при исполнении кода. На самом деле – эта идеология (с т.з. структуры СУБД) уже была применена в АХ 2009 в таблицах InventJournalTrans и InventJournalTrans_Tag, а также в LedgerJournalTrans и LedgerJournalTrans_Asset, LedgerJournalTrans_Project, LedgerJournalTrans_RCash, LedgerJournalTrans_RAsset, LedgerJournalTrans_RDeferrals. Все эти таблицы связаны друг с другом отношением 1:0 или 1:1 (т.е. к примеру – в таблице LedgerJournalTrans_Asset может присутствовать только одна запись для одной записи в LedgerJournalTrans или же полностью отсутствовать, если запись в LedgerJournalTrans не имеет отношения к международным Осам). Связка осуществляется по RecId. Из этого списка несколько выпадают таблицы LedgerJournalTrans_RDeferrals (здесь в одной записи – ссылки на две разных записи в LedgerJornalTrans) и InventJournalTrans_Tag (здесь связь осуществляется по JournalId + LineNum, а не RecId). Кстати говоря, эти таблицы так и остались в АХ 2012 без иерархии (т.е. не состоящие в иерархии). Таким образом, всю цепочку таблиц, участвующих в иерархии можно взять и заменить одной большой мегатаблицей, в полях которых будет много пустых данных. Поля в этой одной большой мегатаблице будут состоять из всех полей всех таблиц, участвующих в иерархии (за исключением, безусловно системных полей). Состав функционала иерархии таблиц В АХ 2012 под иерархией (наследованием) таблиц (Table Hierarchy, Table Inheritance) подразумевается: · Функционал ядра, позволяющий строить структуру таблиц, описанную выше, связи между которыми будут осуществляться по RecId родительской таблицы (в нашем примере иерархия двухуровневая и родительскими таблицами являются это LedgerJournalTrans / InventJournalTrans). Важно! RecId производной таблицы совпадает с RecId базовой, т.о. в производной таблице может быть не более одной записи, соответствующей записи в базовой (родительской) таблице. · Функционал наследования методов у производной таблицы (Derived Table) от ее родительской / базовой (Base Table) · Функционал автоматического добавления всех базовых и производных таблиц на форму, при добавлении таблицы из иерархии на форму · Функционал выбора производной таблицы на форме при создании записи (в таблицах, которые являются базовыми к добавляемой – запись создается автоматически при создании записи в таблице, прописанной в датасорсе. Задача разработчика – обеспечить возможность заполнения всех обязательных полей во всех таблицах иерархии при создании записи – иначе запись сохранена не будет). · Механизм настройки иерархии таблиц в АОТ. Запрос, генерирующийся к СУБД на форме Запрос, генерирующийся к СУБД на форме содержит в себе все таблицы из иерархии – как производные, так и базовые (т.к. везде нужно добавлять одно и тоже значение RecId). Т.о. крупная иерархия (состоящая из большого количества таблиц) может привести к большому количеству джойнов, причем связи между таблицами осуществляются по LEFT OUTER JOIN, что не добавляет скорости к выборке (по сравнению с INNER JOIN). Поддержка сортировки и фильтрации таблиц, связанных по LEFT OUTER JOIN на форме появилась в AX 2012, поэтому эти данные можно на форме фильтровать / сортировать, как будто это одна большая мегатаблица. «Академическим» примером наследования таблиц является глобальная адресная книга (DirPartyTable). Посмотрим, как это все будет выглядеть на форме. Для этого создадим простейшую форму, в которую добавим датасорс DirPartyTable И добавим грид с полями из разных таблиц: DirPartyTable.Name DirPerson.BirthMonth DirPerson.BirthYear DirPerson.BirthDay DirOrganizationBase.PhoneticName Поля, помеченные кружочком являются unretrieved, т.е. невыбираемыми (проще говоря, из-за LEFT JOIN там стоит значение NULL, т.к. запись в соответствующей таблице отсутствует). Пустые значения (без кружочка) означают наличие записи в соответствующей таблице и незаполненное поле. На скриншоте видно, что, например, для записи «Coho Receivers» в DirPartyTable отсутствует запись в таблице DirPerson, но присутствует запись в таблице DirOrganizationBase с пустым значением поля PhoneticName. Запрос, отправляемый к СУБД в этом случае выглядит так: В виде T-SQL: Если же мы вдруг решили добавить на форму таблицу из середины иерархии, к примеру OmInternalOrganization, то запрос к СУБД в этом случае будет выглядеть так: В виде T-SQL: В этом примере наглядно видно, как из запроса исчезла таблица DirPerson, т.к. она не является ни базовой ни производной к таблице OmInternalOrganization. Также обращаю внимание на появление CROSS JOIN-ов к базовым таблицам. Вопрос осмысленности добавления таблицы из середины иерархии я оставляю в стороне, т.к. цель данной статьи – показать, как это будет работать в различных вариантах исполнения. А понимание бизнес-применения наследования таблиц придет со временем. Процедура создания иерархии таблиц 1. Создать обе таблицы (базовую и производную), как элементы в АОТ без дополнительных полей. 2. Создать в базовой таблице поле типа Int64, наследованное от типа \System Documentation\Types\RelationType и назвать его InstanceRelationType (должно быть точно такое название). В этом поле будет храниться код производной таблицы (TableId). 3. На базовой таблице включить свойство SupportInheritance = Yes и выбрать в свойстве InstanceRelationType одноименное только что созданное поле. Сохранить базовую таблицу. 4. На производной таблице включить свойство SupportInheritance = Yes и выбрать в свойстве Extends базовую таблицу. Автоматически создастся Relation на базовую таблицу. Сохранить производную таблицу. Свойства созданного Relation: 5. Добавить остальные необходимые поля в базовую и производную таблицу. Версия системы Данная статья подготовлена по версии АХ 2012: Kernel version: 6.0.947.0 Application version: 6.0.947.0 Обсуждение на форуме ранее axdaily: Table inheritance Наследование таблиц в 2012, кто нибудь уже использовал ? Обновление для версии R2 и R3 В AX2012 R2 механизм наследования таблиц немного изменили. На уровне АОТ механизм остался таким же как и был, а вот на уровне СУБД - теперь вся цепочка таблиц представляет собой одну большую базовую табличку, в которой собраны все поля из производных таблиц. Т.о. в вышеописанном примере все поля из таблички DirPerson и DirOrganizationBase "переехали" в DirPartyTable. А сами таблички исчезли из общего списка таблиц (их нет в БД; в т.ч. их описания нет в SQLDictionary). В частности, теперь не стало таблички CompanyInfo, т.к. она также наследуется от DirPartyTable и, как следствие, все поля из этой таблички были перенесены в DirPartyTable. Соответственно, все запросы (в т.ч. обновления данных) к БД упростились, т.к. теперь выборка осуществляется из одной таблицы, в случае подцепления любой таблицы из иерархии в датасорс формы. Разница в выборке из производной таблицы и из базовой теперь лишь состоит в количестве полей, перечисленных в конструкции SELECT (при выборке в Х++ из производной таблицы - запрос к БД посылается к базовой таблице, но только по тем полям, которые перечислены в АОТе в производной таблице). Правда, выборка из производной таблицы дополнительно фильтруется по тем записям, которые относятся только к ней. Т.е. запрос в Х++ X++: select dirPerson Обращаю внимание на дополнительный фильтр по полю InstanceRelationType - он обеспечивает отбор только тех записей, которые должны относиться к DirPerson А запрос в Х++ X++: select dirPartyTable Данная информация справедлива для версии R2 CU1 (Ядро и приложение - 6.2.1000.156) В версии R3 (Ядро и приложение - 6.3.164.0) никаких изменений по отношению к R2 по части данной статьи не произошло
__________________
Возможно сделать все. Вопрос времени Последний раз редактировалось sukhanchik; 01.06.2014 в 13:59. |
|
|
За это сообщение автора поблагодарили: mazzy (5), AlGol (2), macklakov (9), Berty Wooster (1), BOAL (9), AK-76 (1), Владимир Максимов (5), db (10), Pustik (5), Logger (10), lev (13), TasmanianDevil (7), ziva (2), AvrDen (1), oip (5), ivas (2), Stitch_MS (3), IvanS (1), Aquarius (1), alex55 (1), S.Kuskov (15), -Dmitry- (0), jeky (2), McArrow (1), Evgeniy_R (1). |
Теги |
ax2012, inheritance, table inheritance, наследование таблиц, полезное |
|
|