🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Custom OR Mapping
This page was created by Alexandra on 2017-10-29. Last edited by Wikiadmin on 2026-07-29.

You can customize object-relational (OR) mapping when you reverse an existing SQL database or when its primary-key and inheritance conventions differ from MDriven defaults. This page is for MDriven Designer users who need to map composite keys, use an existing attribute as a primary key, or prevent a default superclass from receiving its own table.

OR mapping maps model classes, attributes, and associations to database tables, columns, and foreign keys. Use custom mapping only where the database schema requires it; keep default mapping for the remaining classes.

Before you start

This guidance applies to SQL database persistence. It does not apply to XML persistence. MDrivenServer has the described persistence settings as defaults.

If mapping properties are not visible on a package, class, attribute, or association end, select the package and set ORMappingConfigMode to Medium or All.

When changing mapping for an existing database, review the generated mapping before applying a database evolution. The Working with Code and Persistence Mapping page explains how MDriven compares the current mapping with a newly calculated mapping.

Map a composite primary key from a reversed database

A composite primary key is a primary key made from two or more columns. Use it when no single column identifies a row, but the combination does.

For example, a reversed database table named filmactor may contain these columns:

Column Meaning Key role
film_id Identifies a film Part of the primary key; foreign key to film
actor_id Identifies an actor Part of the primary key; foreign key to actor

In the model, filmactor has single-link association ends to film and actor. Map the two database columns consistently on the class and on those association ends.

  1. Select the filmactor class.
  2. Set its PrimaryKey property to film_id,actor_id. Enter the two database column names as a comma-separated list.
  3. Select the single-link end from filmactor to film and set ColumnName to film_id.
  4. Select the single-link end from filmactor to actor and set ColumnName to actor_id.
  5. Generate or inspect the default mapping and verify that both columns form the primary key and that each association uses its intended foreign-key column.

The column names in PrimaryKey must match the column names mapped by the association ends. For the example, film_id maps the film link and actor_id maps the actor link; reversing either name produces an incorrect relationship mapping.

For the complete reverse-engineering workflow, see HowTos:Reverse Engineer a Database.

Use an existing attribute as the database primary key

Use this approach when the model already contains the attribute that the database uses as the key. For example, if Class1 has an attribute named SomePK and the Class1 table must use that value as its primary key, configure the class and the attribute rather than adding a separate default identity column.

Configure the class and attribute

  1. On Class1, configure PrimaryKey and PrimaryKeyMapper for the SomePK key mapping.
  2. Select the SomePK attribute.
  3. Set its SaveAction to Freeze when your application supplies the key value.
  4. Generate or inspect the mapping and confirm that SomePK is the key column for Class1.

SaveAction controls what happens to the attribute during save:

SaveAction Use it when Result
Freeze Your application sets the key value. The value cannot be changed after the object has been saved. This is the normal behavior for an application-assigned primary key.
DBAssigned The database assigns the value, such as an AutoInc field. The value is not set during save and is read again from the database after the save.
None The attribute does not require either of the preceding save behaviors. No freeze or database-assigned behavior is applied by this setting.

For example, choose Freeze for a SomePK value created by the application before saving Class1. Choose DBAssigned when the database creates the value during insert.

Handle the default superclass

Changing the primary key of a child class can conflict with the package's default superclass mapping.

A package can name a DefaultSuperClass, which its other classes inherit from. If no modeled default superclass exists, MDriven uses EcoModelRoot in the standard OR mapping. That root has the standard EcoId key. Mapping a subclass such as Class1 to SomePK while the root remains separately mapped creates an unsupported and inconsistent key arrangement.

For this case, map the root into its child tables instead of creating a root table.

  1. Open the Persistence Mapper (PMP) designer.
  2. Add a DefaultORMappingBuilder component.
  3. Connect the component to the PersistenceMapper's NewMappingProvider. MDriven uses this provider for the mapping calculated from the current model, including design-time create and evolve operations.
  4. Connect the same component to the RunTimeMappingProvider. MDriven uses this provider while the application runs.
  5. Set ChildMapRootClass on the DefaultORMappingBuilder.
  6. Validate the model and generate or inspect the default mapping XML.

With ChildMapRootClass enabled, EcoModelRoot, or a modeled default superclass, does not receive a table of its own. Its mapped attributes are stored in each child class table.

For example, after configuring Class1.SomePK as described above:

  • The Class1 table uses SomePK as its primary key.
  • A class with no custom primary-key configuration, such as Class2, continues to use the configured default key-column convention. If the convention is <TableName>ID, its key is Class2ID.
  • A single link from Class2 back to Class1 is represented by its mapped foreign-key column, for example Class1ID when that naming convention is configured.

Optional naming conventions

The DefaultORMappingBuilder can also control generated foreign-key and identity-column naming. For example, you can choose a convention that appends ID to joinable identity columns, such as Class1ID. This is a naming preference; the essential setting for removing the root table in this scenario is ChildMapRootClass.

Verify the mapping

After any custom OR-mapping change:

  1. Generate code and build the project.
  2. Switch to the PMP designer.
  3. Select Validate Model. Resolve validation errors before evolving the database.
  4. Select Generate default mapping XML when you need to inspect the calculated mapping.
  5. Confirm table names, primary-key columns, foreign-key columns, and inheritance mapping in the generated XML before applying schema changes.

You normally do not need to retain generated mapping XML. During database evolution, MDriven stores mapping information in the database and compares the existing mapping with a newly generated mapping to determine the required database changes.

Mapping-provider roles

Provider Purpose
NewMappingProvider Describes how the mapping should look after database evolution.
OldMappingProvider Describes how the current database is mapped.
RunTimeMappingProvider Supplies the mapping used when the application accesses the database at runtime.

If you configure a DefaultORMappingBuilder for a mapping change, connect it to both NewMappingProvider and RunTimeMappingProvider. Otherwise, the mapping used during evolution and the mapping used at runtime can differ.

See also