---
title: "Создание DataEntity для таблиц, у которых нет натурального ключа"
canonical: https://ontargit.com/kz/create-dataentity-for-table-which-dont-have-natural-key/
date: 2021-08-25 12:07:39
description: "Создание DataEntity для таблиц, у которых нет натурального ключа для экспорта данных из Microsoft Dynamics AX"
keywords: "Создание DataEntity"
categories: [Техническая статья, ERP]
---

**Важное ПРИМЕЧАНИЕ: в примере ниже вы увидите создание объекта для экспорта данных из AX, вы не сможете импортировать данные с таким типом объекта.**

Создание DataEntity для некоторых сценариев, где может потребоваться создать DataEntity, у которого нет естественного ключа (например, InventTrans), или, что еще хуже, таблицы, у которых вообще нет уникального индекса (например, CustTrans). Кроме того, для таких типов сущностей у вас может быть требование – поддержка инкрементального push (что также является проблемой, если ваша таблица для DataEntity не имеет естественного ключа);

Чтобы удовлетворить эти требования, вам необходимо:

2.Создайте объект View (CustTransV) и в свойстве Query – вы должны указать объект CustTransQ, созданный на шаг раньше;

3. Обычно, используя мастер для создания DataEntity, вам нужно выбрать таблицу с естественным ключом, но для этого сценария вы можете выбрать ЛЮБУЮ таблицу с естественным ключом (это только с целью создания объекта DataEntity в AOT – назовем его MyCustTransEntity). Например – вы можете выбрать таблицу InventDim.
4.Убедитесь, что на этом шаге вы сняли все флажки (это означает, что наш вновь созданный DataEntity не будет содержать поля из таблицы InventDim).

5.Удалить таблицу InventDim из источника данных MyCustTransEntity;
6. Drug CustTransV в источник данных MyCustTransEntity;

7. Выберите те поля из CustTransV, которые необходимо экспортировать через DataEntity и лекарство, и перетащите их в узел Fields MyCustTransEntity. Поле CustTransV.RecId также необходимо разместить в узле Fields MyCustTransEntity;
8. Когда вы добавляете поле CustTransView.RecId в узел Fields, вам нужно переименовать его: скажем, из RecId1 во что-то вроде CustTransRecId;
9. Добавьте поле CustTransRecId в узел Entity Index;

После этих операций вам необходимо построить модель с синхронизацией. Итак, на данный момент ваш DataEntity может быть пользователем для экспорта данных. Чтобы использовать этот DataEntity для инкрементного экспорта данных, вам необходимо создать класс, который будет обрабатывать некоторые события класса DMFEntityBase (класс DMFEntityBase отвечает за анализ DataEntities). Итак, ниже вы увидите класс, который позволяет:
1. Используйте представления в качестве источника данных для вашего DataEntity
2. Проверьте, включено ли отслеживание изменений (CT) для вашего DataEntity-&gt; View-&gt; Query-Table
a.Таким образом, он включит / отключит CT, если вы добавите / удалите свой DataEntityl;

Copy to Clipboard
Syntax Highlighter

///

/// Fixing of MS wrong logic if DataSource for DataEntity is View (sourced by Query)

///

using DataManagementSerialization = Microsoft.Dynamics.AX.Framework.Tools.DataManagement.Serialization;

using Microsoft.Dynamics.BusinessPlatform.SharedTypes;

using Microsoft.Dynamics.ApplicationFoundation.DIXF.Instrumentation;

class DMFEntityBase_YourModel_ClassEH

{

const static str qtyOfTablesCTEnabledArgName = ‘qtyOfTablesCTEnabled’;

const static str isCTEnabledArgName = ‘isCTEnabled’;

///

///

///

/// ///

/// Fixing of MS wrong logic if DataSource for DataEntity is View (sourced by Query)

///[PreHandlerFor(classStr(DMFEntityBase), staticMethodStr(DMFEntityBase, DisableCTForEntity))]

public static void DMFEntityBase_Pre_DisableCTForEntity(XppPrePostArgs _args)

{

DMFEntity entityloc = _args.getArg(‘entityloc’);

boolean isCTEnabledForTable = false;

int qtyOfTablesCTEnabled = 0;

DictDataEntity dictDataEntity ;

AifSqlChangeTrackingEnabledTables aifSqlChangeTrackingEnabledTables;

dictDataEntity = new DictDataEntity(tableName2Id(entityloc.TargetEntity));

TableName rootTableName = DMFEntityBase::getRootTableName(dictDataEntity);

if(rootTableName &amp;&amp; entityloc.TargetEntity != «»)

{

isCTEnabledForTable = AifSqlChangeTrackingEnabledTables::find(rootTableName, entityloc.TargetEntity).RecId != 0;

if (isCTEnabledForTable)

{

select count(RecId) from aifSqlChangeTrackingEnabledTables

where aifSqlChangeTrackingEnabledTables.TableName == rootTableName;

qtyOfTablesCTEnabled = aifSqlChangeTrackingEnabledTables.RecId;

}

}

_args.addArg(DMFEntityBase_YourModel_ClassEH::qtyOfTablesCTEnabledArgName, aifSqlChangeTrackingEnabledTables.RecId);

_args.addArg(DMFEntityBase_YourModel_ClassEH::isCTEnabledArgName, isCTEnabledForTable);

}

///

///

///

/// ///

/// Fixing of MS wrong logic if DataSource for DataEntity is View (sourced by Query)

///[PostHandlerFor(classStr(DMFEntityBase), staticMethodStr(DMFEntityBase, DisableCTForEntity))]

public static void DMFEntityBase_Post_DisableCTForEntity(XppPrePostArgs _args)

{

DMFEntity entityloc = _args.getArg(‘entityloc’);

boolean isCTEnabledForTable = _args.getArg(DMFEntityBase_YourModel_ClassEH::isCTEnabledArgName);

int qtyOfTablesCTEnabled = _args.getArg(DMFEntityBase_YourModel_ClassEH::qtyOfTablesCTEnabledArgName);

DictDataEntity dictDataEntity ;

AifSqlChangeTrackingEnabledTables aifSqlChangeTrackingEnabledTables;

TableName rootTableName;

boolean isRecFromAifCTTbleDeleted = false;

AifChangeTrackingQuery query;

AifChangeTrackingDataSource dataSource;

int dataSourceIndex, dataSourceCount;

TableName tableName;

AifSqlChangeTrackingEnabledTables enabledTablesDelete;

AIFSQLCDCENABLEDTABLES ctEnabledTables;

boolean isEntityEnabled, rootCTDisabled;

boolean trigerCTDisabled = false;

AifChangeTrackingScope scope;

int64 ctEnabled = -1;

if (isCTEnabledForTable &amp;&amp; qtyOfTablesCTEnabled &gt; 0)

{

dictDataEntity = new DictDataEntity(tableName2Id(entityloc.TargetEntity));

rootTableName = DMFEntityBase::getRootTableName(dictDataEntity);

select count(RecId) from aifSqlChangeTrackingEnabledTables

where aifSqlChangeTrackingEnabledTables.TableName == rootTableName;

isRecFromAifCTTbleDeleted = qtyOfTablesCTEnabled != aifSqlChangeTrackingEnabledTables.RecId

&amp;&amp; qtyOfTablesCTEnabled &gt; aifSqlChangeTrackingEnabledTables.RecId;

}

if (!isRecFromAifCTTbleDeleted &amp;&amp; isCTEnabledForTable &amp;&amp; qtyOfTablesCTEnabled &gt; 0)

{

scope = entityloc.TargetEntity +»@DMF:DMFExport»;

select count(RecId) from ctEnabledTables where ctEnabledTables.Scope == scope;

isEntityEnabled = ctEnabledTables.RecId &gt; 1 ? true:false;

if(dictDataEntity &amp;&amp; AifSqlChangeTrackingEnabledTables::find(rootTableName, entityloc.TargetEntity).RecId)

{

query = AifChangeTrackingQuery::constructFromDataEntity(dictDataEntity,isEntityEnabled);

ttsbegin;

dataSourceCount = query.dataSourceCount();

for (dataSourceIndex = 1; dataSourceIndex