You can configure how an MDriven model maps to SQL database tables, keys, foreign-key columns, and inheritance when the default persistence mapping does not match the database structure you need.
This page covers SQL database persistence mapping in MDriven. It does not apply to systems using XML persistence mappers. MDrivenServer uses the settings described here as its defaults.
Start with the model, not mapping XML
Object-relational mapping (OR mapping) translates classes and attributes in your model to database tables and columns. MDriven normally calculates this mapping from the model when you evolve the database. You only need to change mapping configuration when the generated defaults do not meet your requirements.
For example, you may want these conventions:
- A shared abstract superclass has no table of its own.
- Attributes inherited from that superclass are stored in each concrete child table.
- Identity columns use names such as
Class1IDinstead of the defaultEco_Id. - Foreign-key columns end in
ID.
Do not normally generate and maintain mapping XML by hand. During database evolution, MDriven compares the mapping stored for the existing database with a newly calculated mapping. That comparison lets MDriven determine the database changes required by model changes.
For background on persistence mapper choices, see Documentation:Persistence mappers. For the broader persistence concepts, see Documentation:Persistence.
Configure child-mapped inheritance
A child-mapped class has no table of its own. Its persistent attributes are instead included in the tables of its child classes. This is useful for an abstract superclass that supplies common attributes to concrete classes.
Consider this inheritance structure:
TheDefaultSuperClassis abstract and providesCreateTimeandChangeTime.Class1inherits fromTheDefaultSuperClassand addsAttribute1.Class2inherits fromClass1and addsAttribute2.Class3is abstract and inherits fromTheDefaultSuperClass.Class4inherits fromClass3and hasAttribute1andAttribute2.
If TheDefaultSuperClass and Class3 are abstract and child-mapped, neither needs a database table. The concrete tables contain the inherited columns required by their mapped class:
| Model class | Table produced | Example columns |
|---|---|---|
TheDefaultSuperClass (abstract, child-mapped)
|
No table | Its attributes are included in concrete child tables. |
Class1
|
Class1
|
Class1ID, ECO_TYPE, CreateTime, ChangeTime, Attribute1
|
Class2
|
Class2
|
Class2ID, ECO_TYPE, Attribute2
|
Class3 (abstract, child-mapped)
|
No table | Its inherited attributes are included in Class4.
|
Class4
|
Class4
|
Class4ID, ECO_TYPE, CreateTime, ChangeTime, Attribute1, Attribute2
|
The mapping uses an identity key and a discriminator. In the generated mapping, an alias identifies the table used by a class, the key implementation identifies its key column, and the discriminator identifies the class type. The following shortened example shows the structure for Class1:
<ClassDef Name="Class1" SuperClass="TheDefaultSuperClass">
<AliasDef Name="Class1_A" Table="Class1" ExtentRequiresDiscriminator="False">
<KeyImpl Name="EcoKey">
<KeyColumn Name="Class1ID" />
</KeyImpl>
<DiscriminatorImpl Name="EcoType" Column="ECO_TYPE" />
</AliasDef>
<DiscriminatorValue Name="EcoType" Value="3" />
<AttributeDef Name="ChangeTime" Alias="Class1_A" Columns="ChangeTime" AttributeMapper="<Default>" />
<AttributeDef Name="CreateTime" Alias="Class1_A" Columns="CreateTime" AttributeMapper="<Default>" />
<AttributeDef Name="Attribute1" Alias="Class1_A" Columns="Attribute1" AttributeMapper="<Default>" />
</ClassDef>
Set up the mapping providers
Use a DefaultORMappingBuilder component in the PMP designer to calculate a mapping from the current model and to select the mapping used at runtime.
- Add a
DefaultORMappingBuildercomponent to the PMP designer. - Set
NewMappingProvidertoDefaultORMappingBuilder1, or to the instance name of the builder you added. - Set
RunTimeMappingProviderto the mapping provider that the application must use when it accesses the database. - Configure the builder and the relevant package or classes as described in the following sections.
- Generate code and build the project.
- Switch to the PMP view, select Validate Model, and then select Generate default mapping XML if you need to inspect the calculated mapping.
Know what each provider does
| Provider | Purpose | Example use |
|---|---|---|
NewMappingProvider
|
Describes the mapping calculated from the current model after a database evolution. | You add Attribute2 to Class2; this provider describes the new Attribute2 column.
|
OldMappingProvider
|
Describes the mapping currently represented by the database. | MDriven uses it with the new mapping to identify what must change in an existing database. |
RunTimeMappingProvider
|
Supplies the mapping used while the application reads and writes the database. | At runtime, Class1.Attribute1 is read from or written to the configured Class1 table column.
|
Configure the default superclass at package level
Set the package so that TheDefaultSuperClass is the default superclass for the other classes in that package. Mark TheDefaultSuperClass as abstract; abstract classes are shown in italic in diagrams.
Then configure that default superclass as child-mapped in DefaultORMappingBuilder. This prevents a separate table for the abstract default superclass and places its attributes in the child tables instead.
For the example above, CreateTime and ChangeTime appear in Class1 and Class4, because those are the concrete mapped classes that inherit them. They do not require a TheDefaultSuperClass table.
Configure names for keys and foreign keys
The default builder also controls naming conventions. Set these conventions when the generated names must be easier to recognize in the database or must align with an existing convention.
| What you configure | Default described by this page | Example alternative | Result |
|---|---|---|---|
| Foreign-key column naming | <Name>
|
Append ID
|
A reference named Customer can use a column ending in ID.
|
| Identity-column naming | Eco_Id
|
<TableName>ID
|
The Class1 table uses Class1ID; the Class4 table uses Class4ID.
|
These conventions make database keys easier to identify when you inspect the schema directly: joinable identity and foreign-key columns consistently end in ID.
Configure mapping for an ordinary class
You can configure OR mapping for an individual, non-default-superclass class in that class's properties.
If the mapping property is not visible on a class, set the package's OrMappingConfigMode setting first. This enables the class-level OR mapping configuration.
Use class-level configuration when one class needs a mapping rule that differs from the package-level default. For example, retain the package convention for most classes while configuring a specific class to use a particular mapping behavior.
Inspect generated mapping XML when diagnosing mapping
Generating default mapping XML is primarily a diagnostic and learning tool. It appends an XML file to the project so that you can see the mapping MDriven calculated from the model and configuration.
A generated mapping contains both:
- Class mapping definitions, including aliases, keys, discriminators, and attribute-to-column mappings.
- Database table definitions, including columns and indexes.
For example, a concrete Class1 definition can declare Class1ID as its key column, map the discriminator to ECO_TYPE, and map Attribute1 to the Attribute1 column. Its table definition then includes those columns and a primary-key index on Class1ID.
Do not treat this generated XML as the normal place to make model changes. Change the model and mapping configuration, then let MDriven calculate the updated mapping for database evolution.
Work with an existing database
When mapping must match an existing database, OR mapping can be customized beyond the defaults described here. You can also reverse derive a model from a database. Database schema alone may not contain every association or key detail needed for a complete model, so review and supplement the result where necessary.
See HowTos:Reverse Engineer a Database for the reverse workflow and for adding missing primary-key, attribute, and association information.
Map special attribute types
The model's attribute type must resolve to an available .NET type when MDriven builds the runtime model and derives code. MDriven resolves type names through EcoDataTypes.xml; if it cannot find a definition for a common type name, it treats that type as String.
A persistence mapper defines how a .NET type is handled by the database for inserts, updates, deletes, and selects. You can assign a mapper at the attribute level through the attribute's PersistenceMapper property, or configure a mapper for a common name or .NET type before the EcoSpace starts. See Documentation:Type mapping, OR-Mapping for the type-resolution and custom-mapper details.
For database-generated GUID values, see Documentation:Autoguid.
