Download as pdf or txt
Download as pdf or txt
You are on page 1of 3

Archive customization through extension v1.

Introduction
Every transaction data in ERP system has a journey. When data is first entered in the system it requires
frequent access. Over a period of time transactional data becomes stale and eventually needs to be
archived or purged.

Archive framework in Dynamics 365 provides a mechanism to transition transactional data through its
various lifecycle stages.

Lifecycle Stages

• Live: The data needs frequent access to run day to day business operations. It requires optimized
storage and increased indexing to support its access requirements.

• History: The data has been finalized but still is used in the system for infrequent access,
reporting or analytics. The storage and indexing requirements for data are significantly less.

• Long Term Retention (LTR): The data is kept only in secondary storage (Dataverse LTR) for rare
access scenarios such as auditing, regulatory, legal and compliance purposes. LTR data is
removed from primary storage (SQL Server).

• Purge: When data is no longer needed, it is removed from LTR or directly from live or history
tables (no retention scenario).

Move data to history


The principle behind moving data from live to history is simple. Transactions records are moved as is to
the history tables. Therefore, it is must that the underlying history table structures for transactions
match with the structure of its corresponding live table.

Example:

In picture below for N = 4, a transaction record will be saved in 5 separate tables (1 parent and 4 children
tables) with depth of hierarchy being 1. Archive framework supports N levels of hierarchy depth.

1
Archive customization through extension v1.0

All columns in a live table must be present in its mirrored history table.

Columns exclusion Rule: SysRowVersion and SysDataState tables are added by the system and are
managed via table metadata properties. These columns are not required to be added to the history
table.

Beginning in release 10.0.34 D365 Finance & Operations supports archiving of General Ledger and Sales
Order transactions in the standard product. Development in other uptake areas is in progress to support
archiving of their transaction data.

Add fields to history table through extension


Often customers will have custom fields added to live tables to support their business operations.
Archive framework requires that the live table columns be mirrored in the corresponding history tables
including the additional columns that are added via extensions to the live table.

Refer to documentation on how to add fields to history tables through extension in D365 Finance &
Operations: https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/extensibility/add-
field-extension

Add additional table to archive scope


Additional transaction tables can be added to archive scope if they are related to the parent live table
directly or via tables in its hierarchy chain.

Create history table corresponding to the live table being added to the archive scope using the following
convention:

1. Mirror all fields from the live table to the history table including all metadata properties on the
live table. See column exclusion rule above.
2. Do not mirror indexes from the live table to the history table. For most history tables, a clustered
index on RecId column should be sufficient. Add additional column to index based on query
needs and to maintain table relations needs such as a foreign key index.
3. Add the created history table add its corresponding live table to the archive scope. Archive
scopes is defined by archive job configuration which is managed by the corresponsing archive
type registered in process automation. Archive framework uses process automation framework
for archive job scheduling and communication with archive microservice to move the data to
history.
4. Find archive type class that implements ArchiveServiceICreateArchiveJob interface. From this
class find ArchiveAutomationJobRequestCreator class for the archive type. Create extension of
ArchiveAutomationJobRequestCreator class to extend createPostJobRequest() method to add
new tables in archive scope using Chain of Command (CoC) design pattern.
5. In the extension class, see example below to add new tables to the archive scope by extending
createPostJobRequest() method. Also refer to the original code to understand how archive
contract is built to define the archive scope.

2
Archive customization through extension v1.0

Example: extending general ledger archive job request creator class to add an additional table.
[ExtensionOf(classStr(LedgerArchiveAutomationJobRequestCreator))]

final class public final class LedgerArchiveAutomationJobRequestCreator_Extension

public ArchiveJobPostRequest createPostJobRequest(LedgerArchiveAutomationCriteria _criteria)

ArchiveJobPostRequest postRequest = next createPostJobRequest(_criteria);

ArchiveServiceArchiveJobPostRequestBuilder builder =
ArchiveServiceArchiveJobPostRequestBuilder::constructFromArchiveJobPostRequest(postRequest);

// Using builder add additional live tables, history tables, join conditions and where conditions (if needed)

// Example: Adding new ledger trans settlement table

DictTable generalJournalAccountEntryTable = new DictTable(tableNum(GeneralJournalAccountEntry));

str generalJournalEntryTableName = generalJournalEntryTable.name(DbBackend::Sql);

DictTable newLedgerTransSettlementTable = new DictTable(tableNum(NewLedgerTransSettlement));

DictTable newLedgerTransSettlementHistoryTable = new DictTable(tableNum(NewLedgerTransSettlementHistory));

str nltsTableName = newLedgerTransSettlementTable.name(DbBackend::Sql);

str nltsHisTableName = NewLedgerTransSettlementHistoryTable.name(DbBackend::Sql);

builder.addDataSource(nltsTableName, nltsHisTableName, generalJournalAccountEntryTableName)

.addJoinCondition(

nltsTableName,

newLedgerTransSettlementTable.fieldName(fieldNum(NewLedgerTransSettlement, TransRecId), DbBackend::Sql),

generalJournalAccountEntryTable.fieldName(fieldNum(GeneralJournalAccountEntry, RecId)))

.addPartitionWhereCondition(nltsTableName);

return builder.finalizeArchiveJobPostRequest();

You might also like