In AX 2012, relations are no longer supported under Extended Data Types.
During an upgrade where you are re-implementing, it's common to import database schema via XPO to get your table structure with EDTs.
Sometimes EDTs that are brought over end up pointing to non-existent tables and/or and you change/rename tables, things get broken.
My first time running this tool, it errored with "
The table does not exist."
Which was due to an EDT that was imported that had a broken table relation.
This job will loop over every CUS+ EDT, and if it has a relation, check if it's valid. If it is not, it will create a private project of the EDTs with errors. You can easily change it to search different layers/models/etc. I only limited to the CUS layer for performance.
static void JobCreateProjWithBrokenEDTs(Args _args)
{
#define.ProjName('BadEDTs')
SysProjectFilterRunBase projectFilter = new SysProjectFilterRunBase();
ProjectNode projectNode;
UtilElements utilElements;
SysModelElement modelElement;
SysModelElementType modelElementType;
SysModelElementData modelElementData;
SysDictType sysDictType;
SysDictRelation sysDictRelation;
TableId tableId;
SysDictTable sysDictTable;
SysDictField sysDictField;
FieldName fieldName;
int i;
void addBadEDT(SysModelElement _modelElement)
{
utilElements = null;
utilElements.Name = _modelElement.Name;
utilElements.ParentID = _modelElement.ParentId;
utilElements.RecordType = _modelElement.ElementType;
if (utilElements.RecordType == UtilElementType::SharedProject ||
utilElements.RecordType == UtilElementType::PrivateProject ||
utilElements.RecordType == UtilElementType::ClassInternalHeader ||
utilElements.RecordType == UtilElementType::TableInternalHeader ||
!projectFilter.doUtilElements(utilElements))
{
info(strfmt("@SYS316339", strfmt('%1 %2', utilElements.RecordType, utilElements.Name)));
}
}
projectFilter.grouping(SysProjectGrouping::AOT);
while select modelElement
join Name from modelElementType
where modelElementType.RecId == modelElement.ElementType &&
modelElementType.RecId == UtilElementType::ExtendedType
join modelElementData
where modelElementData.ModelElement == modelElement.RecId &&
modelElementData.Layer >= (UtilEntryLevel::cus-1)
{
sysDictType = new sysDictType(modelElement.AxId);
if (sysDictType)
{
sysDictRelation = sysDictType.relationObject();
if (sysDictRelation)
{
tableId = sysDictRelation.table();
sysDictTable = new SysDictTable(tableId);
if (sysDictTable)
{
// Found an EDT with a valid table, check if the field
// relations are good
for (i = 1; i <= sysDictRelation.lines(); i++)
{
fieldName = fieldid2name(tableId,sysDictRelation.lineExternTableValue(i));
sysDictField = new SysDictField(sysDictTable.id(),fieldname2id(sysDictTable.id(),fieldName));
if (!sysDictField)
{
// Field relation is bad on EDT
warning (strFmt("%1 found table, missing field on table %2", sysDictType.name(), sysDictTable.name()));
addBadEDT(modelElement);
}
}
}
else
{
// Found an EDT with a broken table relation
warning(strFmt("%1 missing valid table", sysDictType.name()));
addBadEDT(modelElement);
}
}
}
}
SysUpgradeProject::delete(#ProjName, ProjectSharedPrivate::ProjPrivate);
projectNode = SysTreeNode::createProject(#ProjName);
projectFilter.parmProjectNode(projectNode);
projectFilter.write();
info(strFmt("Created private project %1", #ProjName));
}