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

You can define model-friendly attribute type names and control how those types are represented in an SQL database; this page is for developers extending type resolution or assigning a custom persistence mapper.

Overview

In MDriven, an attribute type written in the model is a common name. A common name is resolved to an available .NET type when ECO creates the runtime model and when code is derived from the model.

For example, you can model an attribute as Text or CrazyType rather than entering a fully qualified .NET type name in every model attribute. The type definition tells ECO which .NET type that common name represents. A persistence mapper then determines how that .NET type is read from and written to the database.

Term Meaning Example
Common name The type name used on a modeled attribute. Text
Canonical name The name that identifies a type definition in EcoDataTypes.xml. ClassLibrary1.CrazyType
.NET type The runtime type that ECO and derived code must be able to load. ClassLibrary1.CrazyType, ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5348474bcfb2dae2
Persistence mapper (PMapper) The component that defines how a .NET type is handled for database inserts, updates, deletes, and selects. StringAsText

Map a common name to a .NET type

Define the mapping in EcoDataTypes.xml.

  • For ECO, the file is in <installdir>/Config/.
  • For AppComplete, the file is in the application's bin folder.

The referenced class library must be loadable from the supplied type description. In particular, ECO may require the class library to be installed in the GAC because Visual Studio's assembly-loading location for non-GAC assemblies is not predictable.

Example: add a custom value type

The following definition lets a modeled attribute use either CrazyType or ClassLibrary1.CrazyType as its common name. Both resolve to the same .NET type.

<Type CanonicalName="ClassLibrary1.CrazyType"
      Type="ClassLibrary1.CrazyType, ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=5348474bcfb2dae2">

  <CommonName Name="CrazyType" CaseSensitive="false"/>
  <CommonName Name="ClassLibrary1.CrazyType" CaseSensitive="false"/>

  <LanguageName Language="C#" Name="ClassLibrary1.CrazyType"/>
  <LanguageName Language="Delphi" Name="ClassLibrary1.CrazyType"/>
  <LanguageName Language="Oxygene" Name="ClassLibrary1.CrazyType"/>
  <LanguageName Language="VB" Name="ClassLibrary1.CrazyType"/>
</Type>

CaseSensitive="false" means that ECO does not require an exact letter case for that common name.

Important: an unresolved common name becomes String

If ECO cannot find a definition in EcoDataTypes.xml for a common name, it treats the attribute as String. It does not report an error for this fallback.

For example, if an attribute is modeled as CrazyType but its CommonName entry is missing or cannot be loaded, ECO handles it as a string. Verify the type definition and assembly availability before relying on a custom type.

Assign a persistence mapper

A persistence mapper defines how a real .NET type is handled by the database, including inserts, updates, deletes, and selects. To create a custom mapper, implement IGenericSingleColumnAttributemapping.

Register the mapper with SetPMapper before the EcoSpace starts. Registering it after startup is too late because the runtime model has already been prepared.

PersistenceMapperXXX.SqlDatabaseConfig.SetPMapper(
    "CommonName",
    typeof(YourPMapper));

The registration key can identify more than a common name. ECO can resolve a mapper from:

  • A common name, such as Text.
  • A specific modeled attribute, using Class.Attribute.
  • A .NET type.

For example, this registration replaces the mapper selected for System.Int:

PersistenceMapperXXX.SqlDatabaseConfig.SetPMapper(
    "System.Int",
    typeof(YourPMapper));

Use a type-wide registration only when every attribute of that type should use the replacement behavior. Use an attribute-specific mapper selection when one attribute has different storage requirements.

Choose the mapper on a modeled attribute

Each modeled attribute has a PersistenceMapper property. If you cannot see this property in MDriven Designer, select the package and set ORMappingConfigMode to Medium or All.

The recommended setting is <Default>. With this setting, ECO first resolves the attribute's common name to a .NET type and then finds the persistence mapper registered for that type.

Attribute PersistenceMapper value Result Use it when
<Default> ECO resolves the common name to its .NET type and selects the mapper for that type. A tagged value in the type definition can replace this default. The normal mapping is appropriate.
A registered mapper name ECO uses that mapper for the attribute, even if another mapper is the default for its resolved .NET type. One attribute needs special database handling.

For example, an attribute whose common name resolves to System.String normally uses the mapper selected for that .NET type. If the attribute's PersistenceMapper property names a custom mapper, that attribute uses the custom mapper instead.

Set mapper defaults in EcoDataTypes.xml

A type definition can supply tagged values to the runtime model. This allows a common name to select a mapper while the model attribute remains set to <Default>.

The following example defines Text as System.String. It assigns the StringAsText mapper and sets Eco.Length to -1 for attributes using this type.

<Type CanonicalName="Text" Type="System.String">

  <CommonName Name="text" CaseSensitive="false"/>
  <CommonName Name="memo" CaseSensitive="false"/>

  <LanguageName Language="C#" Name="string"/>
  <LanguageName Language="Delphi" Name="string"/>
  <LanguageName Language="Oxygene" Name="string"/>
  <LanguageName Language="VB" Name="String"/>

  <TaggedValue Tag="Eco.PMapper" Value="StringAsText"/>
  <TaggedValue Tag="Eco.Length" Value="-1"/>
</Type>

With this definition, an attribute modeled with common name Text can retain PersistenceMapper = <Default>. The type definition replaces that default with StringAsText at runtime.

A complete selection example

Assume a model contains Document.Body with the attribute type Text.

  1. ECO finds Text in EcoDataTypes.xml.
  2. The type definition resolves Text to System.String.
  3. The attribute has PersistenceMapper = <Default>.
  4. The Eco.PMapper tagged value in the type definition selects StringAsText.
  5. ECO uses StringAsText when it persists Document.Body.

If Document.Body instead names a registered mapper directly in its PersistenceMapper property, ECO uses that named mapper for this attribute.

Scope and related mapping configuration

This page covers the type-to-.NET-type and type-to-persistence-mapper selection path. OR mapping is the broader process of representing modeled objects in relational storage. For SQL database mapping configuration, generated mapping XML, runtime mapping providers, inheritance mapping, and database naming settings, see Documentation:Working with Code and Persistence Mapping.

Use Documentation:Custom OR Mapping when you need to adjust the generated relational mapping rather than select a mapper for an attribute type. For the built-in simple attribute types, including String, Text, Double, Decimal, Integer, DateTime, Boolean, Blob, and Guid, see Documentation:Autoguid.

See also