🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Data transformation
This page was created by Stephanie on 2024-04-05. Last edited by Wikiadmin on 2026-07-29.

You can choose and design the right MDriven data transformation approach when you need to reshape model data for a user interface, another system, an import, or a new object structure.

What data transformation means

Data transformation changes how data is represented, copied, interpreted, or moved from one structure to another. In MDriven, the appropriate technique depends on whether you are:

  • changing the type of data already stored in the database;
  • presenting model data in a use-case-specific shape;
  • creating a new object graph from an existing object graph;
  • importing external tab-separated or JSON data; or
  • transforming XML text.

For example, converting a persisted Price attribute from Integer to Decimal is a database evolution task. Creating an Invoice from an Order is an object-structure transformation task. These are different operations and should not use the same solution.

Choose the transformation approach

Your goal Use Example
Change the type or name of a persisted attribute Attribute or Data Type Conversion Change Price from Integer to Decimal while retaining existing values.
Shape model data for one UI, report, API, or integration use case ViewModel Expose an order's date, customer name, and calculated total in the form required by a screen.
Copy or transform one object structure into a newly created destination object structure ViewModel-based transformation Create a new Order or Invoice and populate matching data from a source object according to a ViewModel recipe.
Load tab-separated external data and update or create objects Import Data Import product codes and names, updating an existing product when its key is found.
Read or write JSON through a ViewModel-defined hierarchy JsonToObject vs Tajson Use TaJSon when the ViewModel should define the hierarchy used for both JSON output and input.
Transform an XML string using XSLT XsltTransformXml Replace an XML root element while retaining the remaining XML content.

Transform object structures with a ViewModel

A ViewModel is a transformation layer between the model and a specific consumer, such as a user interface, report, or external system. It can contain logic that is unique to that context, while reusable business rules remain in the model.

A ViewModel can also describe how to copy or transform an object structure. The transformation uses the ViewModel as a recipe and a destination root object. It then follows the destination structure described by the ViewModel.

For example, you can define a ViewModel that describes the information shared by an order and an invoice. An action can create a new invoice destination object and transform an order into it. This avoids imperative code that individually copies each value and creates each related object.

How matching works

The transformation matches data by ViewModel column names and the receiving object structure. This is the duck-typing principle used here: data can be transferred when the source and destination structures match by the names defined in the ViewModel.

Turn on duck-type checking when designing this kind of ViewModel. The check validates the transformation definition and makes mismatched names or incompatible structures visible before you rely on the transformation.

For example, if a ViewModel column is named SomeDateTime, the receiving object must provide the corresponding named data for that value to be transferred. If an order is transformed into an invoice, define and validate the ViewModel so that the intended order values have matching destinations on the invoice structure.

Control what is copied

The ViewModel structure determines whether transformation copies values, links, or related objects.

ViewModel definition Transformation result Example
Attribute included in the ViewModel Copies the attribute value. Copy an order date to the new invoice date.
Link included without a nested ViewModel class Copies the link to the existing object rather than copying the object at the other end. Copy the link from an order to its existing customer.
Link with a nested ViewModel class Creates and populates a copy of the related object according to that nested structure. Copy order details into newly created invoice details.

For multi-links, the same distinction is important. A nested ViewModel class instructs the transformation to create related objects. Without it, the transformation copies the relationship rather than the object data. Review both ends of an association when transforming multi-links, because association multiplicity affects the resulting links.

Apply transformation rules in the ViewModel

You can define expressions in the ViewModel to change values during a copy. This keeps the copy rules in one visible definition rather than spreading them through UI code.

For example, a revisioning workflow can deep-copy a detailed definition and alter selected values for the new revision. A rule can use the original value and append new for the copied value. Users start with the existing structure and update only the values that differ, while the original revision remains available.

Use this pattern when a user needs a starting copy of an existing object graph. Do not build a blank form and require the user to re-enter a large structure that already exists.

Use transformation in an action

Use a ViewModel transformation when an action must create a destination object and fill it from a source object.

  1. Define the source data and destination structure in a ViewModel.
  2. Include attributes that must be copied.
  3. For each association, decide whether the result should retain a link to the existing object or create a new related object. Add a nested ViewModel class only when related objects must be copied.
  4. Add ViewModel expressions for values that must differ in the destination.
  5. Enable duck-type checking and correct mismatches before using the definition.
  6. In the action, create the destination root object. The transformation operation requires the ViewModel and this destination object.
  7. Execute the action and inspect the created root object and related objects.
  8. Save the transaction only after you have verified the result.

For example, an action named “Create new revision” can create a new revision object, transform the selected revision into it using the revision ViewModel, and open the new object for editing. The user can cancel without saving; in that case, the created work is rolled back. If the user saves, the new persistent objects created by the transformation are saved to the database.

Keep transformation logic in the right layer

Put logic in a ViewModel when it is specific to one transformation context. Put logic in the model when it represents a business rule that multiple contexts must use.

For example, formatting a name for one export is ViewModel-specific transformation logic. A rule that determines whether an order may be invoiced is model business logic and should be reusable outside that export or screen.

This separation lets you test transformation logic independently of the UI, reuse the same ViewModel for equivalent use cases, and keep UI implementations from becoming the only location of business behavior. See The ViewModel for the rationale and design approach.

Handle persisted data changes safely

Do not use object transformation as a substitute for a planned database type conversion. Changing persisted data types can cause data loss and requires careful handling.

Before changing an existing persisted attribute, back up the database. Then use the options described in Attribute or Data Type Conversion:

  • the FormerNames property when renaming an attribute as part of a type conversion;
  • a method with OCL and EAL expressions when you need explicit conversion or need to combine multiple attributes;
  • a derived attribute when you want to test a new representation without modifying stored data; or
  • SafeCast where appropriate.

For example, create a derived Decimal price while retaining the original Integer price to verify calculations. When the result is correct, perform the deliberate persisted-data migration described on the conversion page.

Transform external data

External data has its own structure and keys. Define how it maps to the model instead of assuming that a source file or JSON payload matches your model exactly.

Tab-separated import

Import Data uses a ViewModel to describe the receiving data. You select the ViewModel in the EcoSpaceDebugger, obtain its column headers, paste tab-separated rows, and run the import. Review the Dirty Objects list and save the imported objects when the result is correct.

The UseKey setting uses the first imported column to look up an existing object. If an object is found, that row updates it; otherwise, the import creates a new object. You can also provide criteria to direct imported rows to the intended existing object.

For example, import rows with a product code as the first column. Configure the key lookup so that an existing product with that code is updated, while a code not found creates a new product.

Use PickLists in the ViewModel when imported data must establish links. The lookup uses the result of the associated ViewModel class expression. To create link objects, provide the two association keys in the first two columns.

JSON

JsonToObject vs Tajson explains two different JSON strategies. JsonToObjects creates new objects and expects matching names, without a transformation layer between JSON and the model. TaJSon uses a ViewModel as the template for both reading and writing object hierarchies, making the ViewModel the explicit mapping layer.

XML

Use selfVM.XsltTransformXml(<xsltstring>, <xmlstring>) to transform an XML string with XSLT. The first argument contains the XSLT text, the second contains the XML input, and the result is a new transformed XML string. See XsltTransformXml for the full example.

Verify results before saving

Transformations can create objects, change values, update existing records, or establish links. Verify the result before committing it.

  1. Test with representative data, including an object with related objects and an object with no related objects.
  2. Confirm that copied links point to the intended existing objects.
  3. Confirm that nested structures create new objects only where you intended them to.
  4. Check transformed values, especially calculated or renamed values.
  5. For imports, inspect Dirty Objects before saving.
  6. Back up the database before any persisted type conversion.

See also