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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 04.06.2009, 08:18   #1  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
375 / 562 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
DAX 2009 & UtcDateTime & Primary Key
Доброго времени суток!

DAX 2009 (application version 5.0.1000.52)

Наблюдается некоректное поведение функции Global::record2DynaKey, если в первичном ключе таблицы, есть поле типа UtcDateTime, в этом случае строковый ключ строится неправильно, как следствие, использование обратной функции Global::dynaKey2Record, не приводит к ожидаемому результату.

Видимо реализация метода Global::record2DynaKey должна быть примерно такой(сделано по аналогии с типом Date) :
X++:
static str record2DynaKey(Common rec)
{
    tableId     tableId     = rec.TableId;
    DictTable   dictTable   = new DictTable(tableId);
    indexId     indexId     = dictTable.indexUnique();
    DictIndex   dictIndex   = dictTable.indexObject(indexId);
    str buf;
    int indexCnt;
    int fieldsInIndex;
    fieldId fieldId;
str any2strLocal(anytype t)
{
    return t;
}
    if (dictIndex.name() == 'RecId')                                            // RecId as index
        return '['+int2str(fieldnum(Common,RecId))+':'+int642str(rec.RecId)+']';
    else
    {
        fieldsInIndex = dictIndex.numberOfFields();
        for (indexCnt = 1; indexCnt <= fieldsInIndex; indexCnt++)
        {
            fieldId    = dictIndex.field(indexCnt);
            buf += '[' + int2str(fieldId) + ':';
            switch (typeof(rec.(fieldId)))
            {
                case Types::Date:
                    buf += date2str(rec.(fieldId),-1,-1,-1,-1,-1,-1, DateFlags::None);
                    break;
                    //SRF -->
                case Types::UtcDateTime :
                    buf += datetime2str(rec.(fieldId), DateFlags::None);
                    break;
                    //SRF <--
                default:
                    //buf += any2StrLocal(strReplace(rec.(fieldId),' ', '%20'));
                    buf += any2StrLocal(rec.(fieldId));
            }
            buf += ']';
        }
        if (dictIndex.allowDuplicates())
        {
            buf += '['+int2str(fieldnum(Common,RecId))+':'+int642str(rec.RecId)+']';
        }
    }
    return buf;
}
По той же причине, проблемы могут возникнуть и в методе buildIndexStr класса SysDataSearchIndexBuilder, реализация примерно следующая :
X++:
 private str buildIndexStr(Common record, List listFieldIds)
{
            fieldId fieldId;
            str ret;
            TextBuffer thisStr = new TextBuffer();
            Integer i, nWords;
            anytype thisFieldValue;
 
        str any2strLocal(anytype t)
        {
            return t;
        }
        ;
            enum.reset();
            while (enum.moveNext())
            {
                fieldId = enum.current();
                switch (typeof(record.(fieldId)))
                {
                    case Types::Date:
                        ret += date2str(record.(fieldId),-1,-1,-1,-1,-1,-1);
                        listFieldIds.addEnd(fieldId);
                        break;
                    //srf -->
                    case Types::UtcDateTime :
                        ret += datetime2str(record.(fieldId));
                        listFieldIds.addEnd(fieldId);
                        break;
                    //srf <--
 
                    default:
                        thisFieldValue = record.(fieldId);
                        thisStr.setText(any2StrLocal(thisFieldValue));
                        ret += thisStr.getText();
                            // Repeat the field ID once per word:
                        nWords = SysSearch::splitIntoWords(thisStr).elements();
                        for (i = 0; i < nWords; ++i)
                        {
                            listFieldIds.addEnd(fieldId);
                        }
                }
                ret += #DELIMITER;
            }
            ret += tablelabel;
                // Search for the table label as well.
            return ret;
        }
Оба метода используют локальную функцию any2strLocal для преобразования, любого типа в строку, однако для типа данных UtcDateTime - данная функция возвращает пустое значение.

P.S. Во вложении проект, эмитирующий данную ситуацию. В нем 1 таблица, 2 джоба и 2 класса(Global и SysDataSearchIndexBuilder, изменения аналогичны написаным в теме, но закоментарены).
job SRF_FindUtcDateTimeTypeInUniqueIndex - выводит список таблиц, в которых в первичном ключе есть поле типа UtcDateTime(в стандарте нашел порядка 10 таких таблиц)
job SRF_TestRecord2DynaKey - эмитирует ошибку функции Global::record2DynaKey. Для того, чтобы пронаблюдать данный эффект в импортируемой таблице создайте одну запись, запустите job, затем внесите изменения в Global и вновь запустите job.
Вложения
Тип файла: xpo SharedProject_SRF_Record2DynaKey - копия.xpo (280.9 Кб, 559 просмотров)
За это сообщение автора поблагодарили: kashperuk (5).
Старый 04.06.2009, 10:05   #2  
George Nordic is offline
George Nordic
Модератор
Аватар для George Nordic
Злыдни
 
4,479 / 1250 (50) ++++++++
Регистрация: 17.12.2003
Адрес: Moscow
Записей в блоге: 9
Простите, а что заставило Вас внести Дату в первичный ключ?

С Уважением,
Георгий
Старый 04.06.2009, 13:56   #3  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,320 / 3547 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Цитата:
Сообщение от George Nordic Посмотреть сообщение
Простите, а что заставило Вас внести Дату в первичный ключ?
Не зная мнения автора по этому вопросу - скажу что это удобная альтернатива RecId (когда на таблице нет другого ключа). Замечу, что это не просто дата, а дата+время.

В свое время, я разбирался с клиент-банком от BankSoft Systems (BSS) - и там в таблицах по выпискам (или платежкам - точно не помню) (софтина локальная, а не веб) именно таким образом сделан первичный ключ. Впоследствии - очень наглядно получается при анализе записи - можно с точностью до миллисекунды определить момент создания записи (кстати, таким образом легко и генерить записи сторонней программой в базе)

Конечно, в рамках преобразования даты в строку в аксапте - производительность сказывается не в лучшую сторону. Но это уже совершенно другая тема.
__________________
Возможно сделать все. Вопрос времени
Старый 04.06.2009, 14:03   #4  
George Nordic is offline
George Nordic
Модератор
Аватар для George Nordic
Злыдни
 
4,479 / 1250 (50) ++++++++
Регистрация: 17.12.2003
Адрес: Moscow
Записей в блоге: 9
А-а-а!!! Не убивай меня. Номерные серии для чего придуманы???

С Уважением,
Георгий
Старый 04.06.2009, 15:03   #5  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,320 / 3547 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Номерные серии - это хорошо. Но когда заполнение производится из кода - то на каждый чих вводить номерные серии (в настройках) тоже тяжело.
Номерные серии не отвечают на вопрос "Когда"
Не каждый с ходу догадается (или решит использовать альтернативу) использовать номерные серии - когда есть такое поле.

Согласен, что по правильному в Аксапте должны использоваться номерные серии. Но представь себе начинающего консультанта - который ломает голову - где в системе отображается "волшебная" номерная серия "Пакет корреспонденции"

Просто до АХ2009 не было поля, содержащего время и дату одновременно. Вот и с появлением новго поля появились новые идеи.
__________________
Возможно сделать все. Вопрос времени
Старый 04.06.2009, 15:11   #6  
konopello is offline
konopello
SAP
SAP
 
628 / 76 (4) ++++
Регистрация: 08.11.2005
Адрес: Минск
Цитата:
Просто до АХ2009 не было поля, содержащего время и дату одновременно. Вот и с появлением новго поля появились новые идеи.
по опыту из SAP работы с данным полем, я не рекомендовал бы добовлять данное поле в ключь там очень много подводных камней встречаеться, проще использовать номерную серию, или же GUID (это из SAP), а для того что бы отвечать на вопрос когда была создана та или иная запись имеються же специальные системные поля которые можно включить для заполнения.
Старый 04.06.2009, 15:13   #7  
George Nordic is offline
George Nordic
Модератор
Аватар для George Nordic
Злыдни
 
4,479 / 1250 (50) ++++++++
Регистрация: 17.12.2003
Адрес: Moscow
Записей в блоге: 9
Ох, я бы за такие "идеи"...

Делайте серию "на всякий случай", назначайте ее. Если есть задача встраивать дату - дату лучше встраивать отдельно. Если так уж надо встриавать дату в нумератор - дорабатывайте номерные серии. А ломать себе голову - это и есть работа консультанта. За нее деньги платят.

А вот сокровенный смысл включения даты в первичный ключ - не понимаю.

С Уважением,
Георгий
Старый 05.06.2009, 01:26   #8  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,320 / 3547 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Согласен с George Nordic. Применительно к Аксапте следует поступать именно так
__________________
Возможно сделать все. Вопрос времени
Старый 05.06.2009, 07:05   #9  
SRF is offline
SRF
Участник
MCBMSS
Axapta Retail User
 
375 / 562 (19) +++++++
Регистрация: 08.08.2007
Записей в блоге: 1
Цитата:
Сообщение от George Nordic Посмотреть сообщение
Простите, а что заставило Вас внести Дату в первичный ключ?

С Уважением,
Георгий
Внести дату в первичный ключ меня заставил эксперимент - проверка работоспособности Global::record2DynaKey(...), а смутила строка :
X++:
indexId     indexId     = dictTable.indexUnique();
Так вот на самом деле правильнее сказать не
Цитата:
в первичном ключе таблицы
а в индексе, который Аксапта посчитает уникальным.

Простите, что ввел в заблуждение первым постом.

А с учетом того, что AX сама создает уникальный индекс на таблице Проблема с индексами, если таковой отсутсвует, то и не обязательно, чтобы в AOT на таблице был уникальный индекс.

Цитата:
Сообщение от George Nordic Посмотреть сообщение
А-а-а!!! Не убивай меня. Номерные серии для чего придуманы???

С Уважением,
Георгий
Согласен, что по возможности нужно использовать номерные серии.

Цитата:
Сообщение от George Nordic Посмотреть сообщение

А вот сокровенный смысл включения даты в первичный ключ - не понимаю.

С Уважением,
Георгий
Здесь - как один из возможных вариантов на мой взгляд - это вопрос производительности. Например, если итоговую выборку по таблице нужно сортировать по дате и полям первичного ключа. Можно создать еще один индекс и продублировать поля первичного ключа и добавить дату, а можно просто добавить дату в первичный ключ(разумеется, если это не нарушает логику работы). Но это отдельная тема для разговора.

P.S. Например, в стандарте Дата в качестве поля первичного ключа присутствует во многих местах, например, на таблице InventTransPosting(Здесь дата как мне кажется несет определенную смысловую нагрузку, а не просто ради производительности добавлена в индекс, но это опять-таки отдельная тема для разговора)
За это сообщение автора поблагодарили: George Nordic (2).
Теги
ax2009, dynakey2record, indexunique, record2dynakey, utcdatetime, баг, ошибка

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
msdynamicsax: DAX 2009 and MS SQL 2008 Blog bot DAX Blogs 0 09.08.2008 14:05
axStart: Microsoft Dynamics AX 2009 Hot Topics Web Seminar Series Blog bot DAX Blogs 0 06.08.2008 12:05
Dynamics AX: Dynamics AX 2009 & SQL Server 2008 Blog bot DAX Blogs 0 10.06.2008 21:08
msdynamicsax: Enterprise Portal development in DAX 2009 Blog bot DAX Blogs 0 18.04.2008 07:06
при построении перекрёстных ссылок выдаётся сообщение об ошибках mmmax DAX: Программирование 10 21.01.2005 12:42
Опции темы Поиск в этой теме
Поиск в этой теме:

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

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

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

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