Create, manage, and extend table maps
Table maps define the fields and methods that operate on one or more record types.
Using table maps that are defined in Application Explorer under Data Model and Maps is a way to capture commonalities between record types more safely. Additionally, using table maps can help prevent incompatible record assignments and simplify business logic for similar tables.
You can create a mapping between tables in the Mapping node or by using the mapping node on the table together with an interface class. You can create some mapping on the map, some on the table, and some on an interface class because you can’t create extensions for table maps.
For example, if you right-click a map or activate the context menu, the Create Extension option is available; however, if you select it, nothing happens. You can create, manage, and extend table maps by using Visual Studio.
Create a map
To add maps to a project, go to the Solution Explorer window, right-click the project or activate the context menu, and then select Add, New item. Then, you can modify these views through the designer and Properties windows. The Table map designer window has a top-level node with a table map name.
The following table lists the top-level property for maps (other nodes work as they would on tables).
Property | Description |
---|---|
Name | Name of the map |
The following table lists the nodes that are available for a table map in the designer.
Node | Description |
---|---|
Fields | To create fields manually, right-click the Fields node or activate the context menu. Then, select New, Field. You can set the Extended data type on the field. |
Field groups | Field groups work similar as they do with tables. |
Mappings | Use to create mapping to tables and to point to map fields in the table. Typically, you perform mappings on a table to do extensions and use interface classes for table-specific logic. |
Methods | Like methods for tables; however, instead of having the same method on similar tables, you can create them on a table map. |
Events | The node exists but isn’t used. |
Manage table maps
You need to build table maps before you can use them.
Extend table maps
While you can extend tables and classes, you can’t extend table maps. To find the Create extension menu item, right-click the item or activate the context menu. No action occurs if you select Create extension. You must set up mappings in the table-to-table maps, and you can extend those tables. Additionally, if you require special logic, you need to use an interface class.
To set up mappings in a table, locate the table in Application Explorer and then open it in the designer. In the Mappings node, as the following image shows, right-click the table or activate the context menu, and then select New Mapping. Then, enter the map name and field mapping that you want to use.
If you need special logic, create an abstract class for the interface. First, you need to create an abstract class for mapping by using the table-map name prefixed with Interface, as shown in the following code sample:
public abstract class MyCustVendMapInterface
{
protected MyCustVendMap myCustVendMap;
private MyCustVendMapInterface origInstance;
protected void new()
{
}
private void initializeMyCustVendMap(MyCustVendMap _myCustVendMap = myCustVendMap)
{
myCustVendMap = _myCustVendMap;
}
public final MyCustVendMap getMyCustVendMap()
{
return myCustVendMap;
}
/// <summary>
/// Creates a <c>MyCustVendMapInterface</c> object based on the provided <c>MyCustVendMap</c> record.
/// </summary>
/// <param name = "_myCustVendMap">A <c>MyCustVendMap</c> record from which to create a <c>MyCustVendMapInterface</c> instance.</param>
/// <returns>The instantiated <c>MyCustVendMapInterface</c> object.</returns>
public static MyCustVendMapInterface createInstance(MyCustVendMap _myCustVendMap)
{
SysPluginMetadataCollection metadataCollection = new SysPluginMetadataCollection();
metadataCollection.SetManagedValue(classStr(MyCustVendMapInterface), tableId2Name(_myCustVendMap.tableId));
MyCustVendMapInterface instance = SysPluginFactory::Instance(identifierStr(Dynamics.AX.Application), classStr(MyCustVendMapInterface), metadataCollection);
if (!instance)
{
throw error(strFmt("@SYS19306", funcName()));
}
instance.initializeMyCustVendMap(_myCustVendMap);
return instance;
}
/// <summary>
/// Create a <c>MyCustVendMapInterface</c> object based on the <c>MyCustVendMap</c> orig-record.
/// </summary>
/// <returns>
/// The instantiated <c>MyCustVendMapInterface</c> object.
/// </returns>
public final MyCustVendMapInterface origInstance()
{
if (!origInstance)
{
origInstance = MyCustVendMapInterface::createInstance(this.getMyCustVendMap().orig());
}
return origInstance;
}
/// <summary>
/// Gets module type.
/// </summary>
/// <returns>
/// The <c>ModuleCustVend</c> module type.
/// </returns>
/// <exception cref="Exception::Error">
/// TableId is not associated with any module type.
/// </exception>
public ModuleCustVend getModule()
{
throw error(strFmt("@SYS19306", funcName()));
}
/// <summary>
/// Initializes the current record by copying all fields from another record.
/// </summary>
/// <param name="_bomMap">
/// A record that is related to the map of <c>BOMMap</c> type.
/// </param>
/// <remarks>
/// Both records relate to the map of <c>BOMMap</c> type.The <c>inventDimId</c> value will be copied as
/// well.
/// </remarks>
[Hookable(false)]
public final void initFromMyCustVendMap(MyCustVendMap _map)
{
myCustVendMap.data(_map);
}
}
For each table that requires specific mapping logic, you need to create a new class that extends the interface class, as the following code sample shows:
using System.ComponentModel.Composition;
/// <summary>
/// The <c>MyCustVendMapMyCustTable</c> class contains <c>MyCustTable</c> table specific functionality and mapped fields
/// related to the <c>MyCustVendMapInterface</c> table map.
/// </summary>
[ExportMetadata(classStr(MyCustVendMapInterface), tableStr(MyCustVendMap)), ExportAttribute('Dynamics.AX.Application.MyCustVendMapInterface')]
public class MyCustVendMapMyCustTable extends MyCustVendMapInterface
{
public ModuleCustVend getModule()
{
return ModuleCustVend::Cust;
}
}
Next, you need to initiate the interface class in methods for the map, as the following code sample shows:
public class MyCustVendMap extends common
{
/// <summary>
/// Create an interface instance.
/// </summary>
/// <returns>
/// The <c>MyCustVendMapInterface</c>.
/// </returns>
public MyCustVendMapInterface myCustVendMapInterface()
{
return MyCustVendMapInterface::createInstance(this);
}
/// <summary>
/// Gets module type.
/// </summary>
/// <returns>
/// The <c>ModuleCustVend</c> module type.
/// </returns>
/// <exception cref="Exception::Error">
/// TableId is not associated with any module type.
/// </exception>
public ModuleCustVend getModule()
{
return this.custVendTransOpenInterface().getModule();
}
/// <summary>
/// Initializes the current record by copying all fields from another record.
/// </summary>
/// <param name="bomMap">
/// A record that is related to the map of <c>BOMMap</c> type.
/// </param>
/// <remarks>
/// Both records relate to the map of <c>BOMMap</c> type.The <c>inventDimId</c> value will be copied as
/// well.
/// </remarks>
public void initFromMyCustVendMap(MyCustVendMap _map)
{
this.MyCustVendMap::myCustVendMapInterface().initFromMyCustVendMap(_map);
}
}
When you create your maps by using the outlined methods, you can make extensions, including:
- Table extensions that enable you to use mapping for a table.
- Code extensions that enable you to change a map’s logic by right-clicking the class or activating the context menu and then selecting Create code extension (Chain of Command). Additionally, you can create pre-event and post-events for methods and use them in an event handler class.