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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 25.09.2018, 13:48   #1  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5813 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Я в свое время столкнулся с тем, что buffer.TableId для таблиц, использующих наследование, зачастую возвращает идентификатор не совсем той таблицы, к которой относится буфер. Вместо этого обычно возвращается идентификатор одной из родительских таблиц, явно фигурирующих в коде во время компиляции - см. также А что такого принципиального в 2012? По моему хороший разработчик без труда в ней разберется Нужную информацию содержит поле buffer.RelationType, но тут есть нюанс: в интерпретаторе Х++ обращение к этому полю безопасно даже для Common, а вот при генерации CIL это приводит к ошибке компиляции. Более безопасным оказалось вызывать buffer.getInstanceRelationType() - он возвращает название конкретной таблицы-наследника либо пустую строку, если таблица не входит в иерархию наследования. В итоге для определения во время выполнения "настоящего" типа табличного буфера с учетом возможного наследования получился такой вспомогательный метод:
X++:
// возвращает tableId таблицы либо, если таблица поддерживает наследование, то tableId конкретного "наследника"
// safe тут относится к генерации кода CIL, которая валится на простом обращении к Common.RelationType
public static TableId getTableIdOrReltaionTypeSafe(Common _record)
{
    TableNameShort  tableName = _record.getInstanceRelationType();
    TableId         ret = tableName2id(tableName);
    ;
    if (!ret)
    {
        ret = _record.TableId;
    }
    return ret;
}
Полученное значение уже можно использовать, скажем, в new DictTable(tableId).makeRecord()
За это сообщение автора поблагодарили: AlGol (3), raz (10), sukhanchik (8), Logger (8).
Старый 25.09.2018, 16:45   #2  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,987 / 3273 (117) ++++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от gl00mie Посмотреть сообщение
...Полученное значение уже можно использовать, скажем, в new DictTable(tableId).makeRecord()
Поправил код с учетом ваших замечаний.

X++:
// обходим баг вызова orig() для табличек с наследованием
// [url=http://axforum.info/forums/showthread.php?p=412642#post412642]Приведение типов для таблиц ax2012[/url]
// [url]http://sashanazarov.blogspot.com/2014/01/dynamics-ax-2012-orig-method-fails-on.html[/url]
// [url=http://axforum.info/forums/showthread.php?p=328140#post328140]Опасный orig[/url]
public static anyType origFieldValue_MRC(Common _common, FieldId _fieldId)
{
    TableId     tableId;
    TableId     tableId4Field;
    FieldName   fieldName;

    Common      commonCasted;
    Common      commonOrig;

    DictTable   dictTable;

    anytype     ret;
    ;

    if (_common.RecId == 0)
    {   // обходим баг
        // [url=http://axforum.info/forums/showthread.php?p=328140#post328140]Опасный orig[/url]
        commonOrig = _common.orig();
        commonOrig.doClear();
        ret = commonOrig.(_fieldId);
    }
    else
    {
        dictTable = new DictTable(_common.TableId);

        if (!(dictTable && dictTable.supportInheritance()))
        {   // обычная табличка без наследования - все как обычно
            commonOrig = _common.orig();
            ret = commonOrig.(_fieldId);
        }
        else
        {   // обходим баг
            // [url]http://sashanazarov.blogspot.com/2014/01/dynamics-ax-2012-orig-method-fails-on.html[/url]
            // решаем проблемы с получением значений из родительских табличек для orig() буфера
            
            dictTable = new DictTable(tableName2id(_common.getInstanceRelationType()));
            
            if (dictTable)
            {
                // ищем tableId в иерархии наследования для которой первой определено поле _fieldId т.е. ту для которой оно было введено, а не отнаследовано.
                fieldName = fieldId2name(_common.TableId, _fieldId);
                tableId4Field = _common.TableId;

                if(fieldName)
                {
                    tableId = dictTable.extends();

                    while(tableId)
                    {
                        dictTable = new DictTable(tableId);

                        if (fieldName2id(tableId, fieldName))
                        {
                            tableId4Field = tableId;
                        }
                        else
                        {
                            break;
                        }

                        tableId = dictTable.extends();
                    }
                }
            }
            
            if (tableId4Field)
            {
                commonCasted = SysDictTable::as(_common, tableId2name(tableId4Field));
                commonOrig = commonCasted.orig();
                ret = commonOrig.(_fieldId);
            }
            else
            {
                // не должны сюда попасть. Можно кидать исключение.
                commonOrig = _common.orig();
                ret = commonOrig.(_fieldId);
            }
        }
    }

    return ret;
}
Старый 25.09.2018, 18:01   #3  
pedrozzz is offline
pedrozzz
Молодой, подающий надежды
Аватар для pedrozzz
MCBMSS
Лучший по профессии 2015
 
164 / 218 (8) ++++++
Регистрация: 18.02.2010
Адрес: Краснодар
Цитата:
Сообщение от gl00mie Посмотреть сообщение
Полученное значение уже можно использовать, скажем, в new DictTable(tableId).makeRecord()
есть "стандартный" метод для этого

X++:
SysDictTable::getConcreteTable(record);

X++:
/// <summary>
/// Gets the ID for the concrete table for a specified table.
/// </summary>
/// <param name="_common">
/// The buffer of the given table whose concrete table must be found.
/// </param>
/// <returns>
/// The table ID of the concrete table for the specified table.
/// </returns>
public static TableId getConcreteTable(Common _common)
{
    DictTable dt=new DictTable(_common.TableId);
    TableId concrete=_common.TableId;
    str tablename;
    //Get concrete table for inheritance
    if(dt && dt.supportInheritance())
    {
        tablename= _common.getInstanceRelationType();
        if(tablename)
        {
            concrete=tableName2id(tablename);
        }
    }
    return concrete;
}
__________________
Кононов Пётр

Последний раз редактировалось pedrozzz; 25.09.2018 в 18:12.
За это сообщение автора поблагодарили: sukhanchik (4), Logger (1), gl00mie (3).
Теги
inheritance, table inheritance, type cast

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
[AX2012] Наследование таблиц. iCloud DAX: Программирование 4 26.03.2014 15:28
AX2012 - изменение связи таблиц на форме DTD DAX: Программирование 4 10.12.2013 16:30
Как сравнить financials dimensions у двух таблиц (AX2012) ? DTD DAX: Программирование 0 17.07.2013 15:16
AX2012: drag'n'drop и поля таблиц wojzeh DAX: Программирование 2 18.01.2012 22:07
приведение типов в select simply2double DAX: Программирование 3 30.09.2004 11:24

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

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

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 02:26.