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

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 15.05.2008, 11:25   #1  
somebody is offline
somebody
Участник
 
128 / 30 (2) +++
Регистрация: 30.04.2003
Адрес: Москва
? поля, содержащие RecId
Dear All!

В Аксапте 3.0 ищу поля-ссылки на RecId (кроме самих RecId). Действую так:

1. Нахожу поля с типами-наследниками recId, кроме собственно полей RecId (через dictType.extend()).
2. Нахожу поля, имеющие связи (указанные как в таблицах, так и в EDT) с полями типов-наследников recId, кроме собственно полей RecId (через dictRelation.loadNameRelation() и dictRelation.loadFieldRelation()).
3. Устраняю дубликаты пар таблица-поле.

Но вот здесь есть такая информация:
Цитата:
Сообщение от Yaroslav Batozskiy
при дефрагментировании RecId я обнаружил, что есть поля со ссылками по Recid, тип которых не наследуется от RecId (в результате чего при экспорте-импорте эти ссылки пересчитаны не будут, т.е. данные в таблице будут повреждены). Пример—поле RTSLSessionTransId в таблице LedgerTrans
И вопрос такой: где-то есть полный список подобных полей из штатного функционала?

P. S. Ясно, что при неграмотной модификации ссылки на RecId могут быть вообще в неких integer-полях любого типа, и узнать об этом можно, лишь прошерстив код на предмет присвоения RecId... Но и не хотелось бы лазить по коду, дабы выяснить то же для штатного функционала.
Старый 15.05.2008, 13:34   #2  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от somebody Посмотреть сообщение
В Аксапте 3.0 ищу поля-ссылки на RecId (кроме самих RecId). Действую так:

1. Нахожу поля с типами-наследниками recId, кроме собственно полей RecId (через dictType.extend()).
2. Нахожу поля, имеющие связи (указанные как в таблицах, так и в EDT) с полями типов-наследников recId, кроме собственно полей RecId (через dictRelation.loadNameRelation() и dictRelation.loadFieldRelation()).
3. Устраняю дубликаты пар таблица-поле.
Рекомендованный способ:
найти все поля, тип которых унаследован от refRecId.
Это специальный тип, который согласно рекомендациям, должен содержать ссылки на RecId.
Но некоторые разработчики рекомендации не используют.

Поэтому окончательный поиск надо делать при помощи вашего подхода.
Но сначала просто выбрать все, что унаследовано от refRecId
__________________
полезное на axForum, github, vk, coub.
Старый 15.05.2008, 13:39   #3  
somebody is offline
somebody
Участник
 
128 / 30 (2) +++
Регистрация: 30.04.2003
Адрес: Москва
Цитата:
Сообщение от mazzy
сначала просто выбрать все, что унаследовано от refRecId
Это входит в мой результат, т. к. refRecId - наследник recId.

Вопрос был - есть ли где-то список "неправильных" полей штатного функционала? Или, может, кто-то знает ещё такие поля?
За это сообщение автора поблагодарили: mazzy (2).
Старый 15.05.2008, 13:51   #4  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от somebody Посмотреть сообщение
Вопрос был - есть ли где-то список "неправильных" полей штатного функционала? Или, может, кто-то знает ещё такие поля?
Попытки были. Но законченного списка не видел.
Были проблемы подобного рода в сопоставлении платежей (по-моему таблица SpecTrans). Куча в зарплате, в налоговом учете в русском генераторе российской отчетности. Я бросил составлять подобный список когда понял, что в каждом сервис-паке он разный. Отличается немного, но отличается.

Кроме того, мы зачастую работаем у клиентов, у которых внедряли другие партнеры.... В этих случаях подобный список вообще непредсказуем.

Поэтому вместо общего списка начал делать конкретные списки для каждого конкретного случая.
__________________
полезное на axForum, github, vk, coub.
За это сообщение автора поблагодарили: somebody (1).
Старый 15.05.2008, 13:52   #5  
mazzy is offline
mazzy
Участник
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,472 / 4494 (208) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
если составите, опубликуете и будете поддерживать подобный список - мегареспект вам и мегауважуха.
__________________
полезное на axForum, github, vk, coub.
Старый 15.05.2008, 14:46   #6  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
Цитата:
Сообщение от somebody
...
Вопрос был - есть ли где-то список "неправильных" полей штатного функционала? Или, может, кто-то знает ещё такие поля?...
Насколько я помню, ответ на него был дан в той же теме, из которой приведена цитата в первом сообщении данной темы. Почитайте ее всю внимательно.
__________________
С уважением,
glibs®
Старый 15.05.2008, 18:00   #7  
somebody is offline
somebody
Участник
 
128 / 30 (2) +++
Регистрация: 30.04.2003
Адрес: Москва
Цитата:
Сообщение от glibs
Насколько я помню, ответ на него был дан в той же теме, из которой приведена цитата в первом сообщении данной темы. Почитайте ее всю внимательно.
Тема умещается на 1 странице. Ответа там нет.
Есть там ссылка на боковую ветку, там несколько примеров проблемных таблиц, дискуссия по LedgerTrans.RTSLSessionTransId и описание работы некоего коммерческого скрипта. Да, мысль была, проверять все integer-поля. Мысль не понравилась... Проще код перелопатить...
Старый 16.05.2008, 08:52   #8  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
Цитата:
Сообщение от somebody
...
там несколько примеров проблемных таблиц
...
Вы спросили про стандартную функциональность.

В 3.0 в стандартной функциональности в 3.0 была одна таблица smmTransLog.
Цитата:
Сообщение от somebody
...
Проще код перелопатить
...
Перелопатьте .
__________________
С уважением,
glibs®
Старый 16.05.2008, 14:08   #9  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
А, вот еще условно проблемная таблица.

SysSearchPath

Почитайте все таки внимательно

Как выполнять дефрагментирование RecID

если действительно серьезно интересуетесь проблемой. Там много полезной информации.
__________________
С уважением,
glibs®
Старый 16.05.2008, 14:15   #10  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
Вот джоб, о котором я веду речь. Писался под 3.0. Но на 4.0, вроде, запускается.

static void findBadRefRecId(Args _args)
{
UtilElements utilElements;
DictTable dictTable;
DictField dictField;
DictType dictType;
TableName prevTable;
Counter i,
result,
fieldsFound,
tablesFound;

Boolean skipField(extendedTypeId _typeId)
{
DictType localDictType = new DictType(_typeId);
;

if (!localDictType)
{
return false;
}

switch (localDictType.id())
{
case typeId2ExtendedTypeId(typeid(recId)) :
case typeId2ExtendedTypeId(typeid(tableId)) :
case typeId2ExtendedTypeId(typeid(ParametersKey)) :
case typeId2ExtendedTypeId(typeid(classId)) :
case typeId2ExtendedTypeId(typeid(FieldNum)) :
case typeId2ExtendedTypeId(typeid(fieldId)) :
case typeId2ExtendedTypeId(typeid(FontSize)) :
case typeId2ExtendedTypeId(typeid(SessionId)) :
case typeId2ExtendedTypeId(typeid(timeOfDay)) :
case typeId2ExtendedTypeId(typeid(Days)) :
case typeId2ExtendedTypeId(typeid(WeekDay)) :
case typeId2ExtendedTypeId(typeid(InventDimFixed)) :
case typeId2ExtendedTypeId(typeid(PrintCopies)) :
case typeId2ExtendedTypeId(typeid(TaxReportField)) :
case typeId2ExtendedTypeId(typeid(JmgSeconds)) :
case typeId2ExtendedTypeId(typeid(Minutes)) :
case typeId2ExtendedTypeId(typeid(Seconds)) :
case typeId2ExtendedTypeId(typeid(Column)) :
case typeId2ExtendedTypeId(typeid(Columns)) :
case typeId2ExtendedTypeId(typeid(Yr)) :
case typeId2ExtendedTypeId(typeid(Months)) :
case typeId2ExtendedTypeId(typeid(NumberSequenceRange)) :
return true;
default :
}

if (localDictType.extend())
{
return skipField(localDictType.extend());
}
return false;

}

str typesChain(extendedTypeId _typeId)
{
DictType chainDictType = new DictType(_typeId);
str ret;
;

if (chainDictType)
{
ret = ret + strfmt(" --> %1", chainDictType.name());
}

if (chainDictType.extend())
{
ret = ret + strfmt("%1", typesChain(chainDictType.extend()));
}
return ret;

}
;

while select utilElements
order by name
where utilElements.recordType == UtilElementType::Table
{
if (prevTable != utilElements.name)
{
dictTable = new DictTable(tablename2id(utilElements.name));
if (!dictTable.isMap() && !dictTable.isView() && !dictTable.isTmp())
{
info (strfmt("%1", dictTable.name()));
tablesFound++;
result = 0;
for (i = 1; i <= dictTable.fieldCnt(); i++)
{
dictField = new DictField(dictTable.id(), dictTable.fieldCnt2Id(i));
if (dictField.baseType() == Types::Integer &&
!dictField.isSystem() && !skipField(dictField.typeId()))
{
dictType = new DictType(dictField.typeId());
info (strfmt(" %1 -- %2",
dictField.name(),
dictType ? typesChain(dictField.typeId()) : int2str(dictField.typeId())));
// if (dictType)
// {
// info (strfmt(" %1 -- %2", dictType.label(), dictType.help()));
// }
fieldsFound++;
result++;
}
}
if (!result)
{
infolog.cut(infolog.line());
tablesFound--;
}
}
}
prevTable = utilElements.name;
}
info (strfmt("Total number of tables found: %1", tablesFound));
info (strfmt("Total number of fields found: %1", fieldsFound));

}
__________________
С уважением,
glibs®
Старый 16.05.2008, 14:18   #11  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,305 / 3533 (124) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Если у вас есть 4-ка (имеется в виду все файлы с установочного диска), то там в подкаталоге DatabaseUpgrade есть проект UpgradeColumnList (для 3-шки), основное назначение которого - подготовить список всех полей, которые нужно обновить при переходе с 3-шки на 4-ку. Поскольку принципиально изменился тип только у полей с RecId (стал 64-битный), то можно считать данный проект - как создание списка всех полей всех таблиц в которых хранится RecId. Плюс в том, что данный проект - от Микрософта - т.е. его (проект) они тестировали (по крайней мере на SQL Server 2005).
Данный проект запускается на 3-шке перед переливкой данных на 4-ку
__________________
Возможно сделать все. Вопрос времени
За это сообщение автора поблагодарили: somebody (1).
Старый 16.05.2008, 14:27   #12  
glibs is offline
glibs
Member
Сотрудники компании It Box
Most Valuable Professional
Лучший по профессии 2011
Лучший по профессии 2009
 
4,942 / 911 (40) +++++++
Регистрация: 10.06.2002
Адрес: I am from Kyiv, Ukraine. Now I am in Moscow. For private contacts: glibs@hotmail.com
Я так подозреваю, что тот проект, как и дефрагментация RecId в 3.0, работает по RefRecId. Вопрос как раз в том, как убедиться в том, что все поля, в которых реально хранится RecId, унаследованы от нужного типа.

Со стандартными таблицами, вроде, все ОК. А вот если есть модификации, то такой проверкой придется заниматься. Микрософт не поможет тут.
__________________
С уважением,
glibs®
За это сообщение автора поблагодарили: somebody (1).
Старый 16.05.2008, 16:14   #13  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,305 / 3533 (124) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Спорить не буду, Микрософт не поможет. Однако - одно дело дописать, а другое дело написать один и тот же код. Заодно и узнать - может какие-то поля "в лоб" прописаны.

Т.е. проект стоит считать шаблоном/примером, но никак не руководством к действию (только после проверки и "подкрутки")
__________________
Возможно сделать все. Вопрос времени
Старый 16.05.2008, 17:50   #14  
somebody is offline
somebody
Участник
 
128 / 30 (2) +++
Регистрация: 30.04.2003
Адрес: Москва
Lightbulb
2 sukhanchik
Как было сказано, собственно поля, созданные согласно рекомендациям, мной уже найдены алгоритмом, описанным в первом сообщении. Поэтому UpgradeColumnList ничего нового не даст.
Вопрос в том, чтобы найти поля, созданные вопреки рекомендациям: с типами, не унаследованными от RefRecId (или уж хотя бы напрямую от recId), и в то же время содержащие значения RecId.

2 glibs
Спасибо за скрипт, это очень хорошая идея, перебрать все подозрительные integer-поля таким образом, пропуская некоторые типы. Я добавил ещё некоторые типы, к-рые стоит игнорировать (IMHO):
TimeUnits PositiveDays PositiveMonths createdTime modifiedTime Periods IntvMth IntvQr IntvWk enumId CCColor OLE_Color MaximumLength MinimumLength CACPriority Priority BatchPeriodic HWND LabelIdNum extendedTypeId ColumnWidth NegativeAdjustment NoOfDecimals OprNum AssetInterval AssetLifeTime AssetLifeTimeRest indexId CovStatus SysCodeProfilerAOS* SysCodeProfilerSQL* OLAPCube* OLAPDatabase* OLAPView*.

В итоге получается довольно обозримый список полей, просмотрев к-рый, получим большую уверенность, что мы ничего не упустили.
Скрипт с добавленными типами и с выводом чуть понагляднее, к-рый теперь запускаю:
X++:
// Находим integer-поля, в которых МОГУТ находиться значения RecId, с типом, не унаследованным от recId
static void findProbablyBadRefRecId(Args _args)
{
    UtilElements utilElements;
    DictTable dictTable;
    DictField dictField;
    DictType dictType;
    TableName prevTable;
    Counter i,
                result,
                fieldsFound,
                tablesFound;

    Boolean skipField(extendedTypeId _typeId)
    {
        DictType localDictType = new DictType(_typeId);
        ;

        if (! localDictType)
        {
            return false;
        }
        switch (localDictType.id())
        {
            case typeId2ExtendedTypeId(typeid(recId)) :
            case typeId2ExtendedTypeId(typeid(tableId)) :
            case typeId2ExtendedTypeId(typeid(ParametersKey)) :
            case typeId2ExtendedTypeId(typeid(classId)) :
            case typeId2ExtendedTypeId(typeid(FieldNum)) :
            case typeId2ExtendedTypeId(typeid(fieldId)) :
            case typeId2ExtendedTypeId(typeid(FontSize)) :
            case typeId2ExtendedTypeId(typeid(SessionId)) :
            case typeId2ExtendedTypeId(typeid(timeOfDay)) :
            case typeId2ExtendedTypeId(typeid(Days)) :
            case typeId2ExtendedTypeId(typeid(WeekDay)) :
            case typeId2ExtendedTypeId(typeid(InventDimFixed)) :
            case typeId2ExtendedTypeId(typeid(PrintCopies)) :
            case typeId2ExtendedTypeId(typeid(TaxReportField)) :
            case typeId2ExtendedTypeId(typeid(JmgSeconds)) :
            case typeId2ExtendedTypeId(typeid(Minutes)) :
            case typeId2ExtendedTypeId(typeid(Seconds)) :
            case typeId2ExtendedTypeId(typeid(Column)) :
            case typeId2ExtendedTypeId(typeid(Columns)) :
            case typeId2ExtendedTypeId(typeid(Yr)) :
            case typeId2ExtendedTypeId(typeid(Months)) :
            case typeId2ExtendedTypeId(typeid(NumberSequenceRange)) :
            case typeId2ExtendedTypeId(typeid(TimeUnits)) :
            case typeId2ExtendedTypeId(typeid(PositiveDays)) :
            case typeId2ExtendedTypeId(typeid(PositiveMonths)) :
            case typeId2ExtendedTypeId(typeid(createdTime)) :
            case typeId2ExtendedTypeId(typeid(modifiedTime)) :
            case typeId2ExtendedTypeId(typeid(Periods)) :
            case typeId2ExtendedTypeId(typeid(IntvMth)) :
            case typeId2ExtendedTypeId(typeid(IntvQr)) :
            case typeId2ExtendedTypeId(typeid(IntvWk)) :
            case typeId2ExtendedTypeId(typeid(enumId)) :
            case typeId2ExtendedTypeId(typeid(CCColor)) :
            case typeId2ExtendedTypeId(typeid(OLE_Color)) :
            case typeId2ExtendedTypeId(typeid(MaximumLength)) :
            case typeId2ExtendedTypeId(typeid(MinimumLength)) :
            case typeId2ExtendedTypeId(typeid(CACPriority)) :
            case typeId2ExtendedTypeId(typeid(Priority)) :
            case typeId2ExtendedTypeId(typeid(BatchPeriodic)) :
            case typeId2ExtendedTypeId(typeid(HWND)) :
            case typeId2ExtendedTypeId(typeid(LabelIdNum)) :
            case typeId2ExtendedTypeId(typeid(extendedTypeId)) :
            case typeId2ExtendedTypeId(typeid(ColumnWidth)) :
            case typeId2ExtendedTypeId(typeid(NegativeAdjustment)) :
            case typeId2ExtendedTypeId(typeid(NoOfDecimals)) :
            case typeId2ExtendedTypeId(typeid(OprNum)) :
            case typeId2ExtendedTypeId(typeid(AssetInterval)) :
            case typeId2ExtendedTypeId(typeid(AssetLifeTime)) :
            case typeId2ExtendedTypeId(typeid(AssetLifeTimeRest)) :
            case typeId2ExtendedTypeId(typeid(indexId)) :
            case typeId2ExtendedTypeId(typeid(CovStatus)) :
                return true;
            default :
        }
        if (localDictType.name() like "SysCodeProfilerAOS*" ||
            localDictType.name() like "SysCodeProfilerSQL*" ||
            localDictType.name() like "OLAPCube*" ||
            localDictType.name() like "OLAPDatabase*" ||
            localDictType.name() like "OLAPView*")
        {
            return true;
        }
        if (localDictType.extend())
        {
            return skipField(localDictType.extend());
        }

        return false;
    }

    str typesChain(extendedTypeId _typeId)
    {
        DictType chainDictType = new DictType(_typeId);
        str ret;
        ;

        if (chainDictType)
        {
            ret = ret + strfmt(" --> %1", chainDictType.name());
        }
        if (chainDictType.extend())
        {
            ret = ret + strfmt("%1", typesChain(chainDictType.extend()));
        }
        return ret;
    }
    ;

    while select utilElements
        order by name
        where utilElements.recordType == UtilElementType::Table
    {
        if (prevTable != utilElements.name)
        {
            dictTable = new DictTable(tablename2id(utilElements.name));
            if (! dictTable.isMap() && ! dictTable.isView() && ! dictTable.isTmp())
            {
                info (strfmt("%1", dictTable.name()));
                tablesFound++;
                result = 0;
                for (i = 1; i <= dictTable.fieldCnt(); i++)
                {
                    dictField = new DictField(dictTable.id(), dictTable.fieldCnt2Id(i));
                    if (dictField.baseType() == Types::Integer &&
                        ! dictField.isSystem() &&
                        ! skipField(dictField.typeId()))
                    {
                        dictType = new DictType(dictField.typeId());
                        info (strfmt("    %1 : %2",
                                    dictField.name(),
                                    dictType ? typesChain(dictField.typeId()) : int2str(dictField.typeId())));
                        fieldsFound++;
                        result++;
                    }
                }
                if (! result)
                {
                    infolog.cut(infolog.line());
                    tablesFound--;
                }
            }
        }
        prevTable = utilElements.name;
    }
    info (strfmt("Total number of tables found: %1", tablesFound));
    info (strfmt("Total number of fields found: %1", fieldsFound));
}
Теги
ax3.0, recid, дефрагментирование recid

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Как выполнять дефрагментирование RecID mazzy DAX: База знаний и проекты 174 05.10.2017 12:59
Denis Fedotenko: Новые поля в складских проводках Blog bot DAX: База знаний и проекты 10 24.05.2007 11:57
aEremenko: Дефрагментация RecID Blog bot DAX Blogs 2 06.03.2007 22:25
Тип поля RecId Eldar9x DAX: Программирование 4 14.11.2006 16:03
Получить значение поля таблицы по номеру (Id) поля Anais DAX: Программирование 2 15.04.2004 13:00

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

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

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