Link Search Menu Expand Document

Implicit Mapping


This feature allows you to implicitly map .NET CLR types or class properties to their equivalent database objects. Dedicated mapper classes are provided as an alternative to using attributes directly on the classes.

Fluent Mapping

Use the FluentMapper class to manage table/property mappings, primary/identity columns, database types, and class/property handlers in a fluent style.

To define mappings for an entity, use the Entity() method:

FluentMapper
    .Entity<Customer>() // Define which Class or Model
    .Table("[sales].[Customer]") // Map the Class/Table
    .Primary(e => e.Id) // Define the Primary
    .Identity(e => e.Id) // Define the Identity
    .Column(e => e.FirstName, "[FName]") // Map the Property/Column
    .Column(e => e.LastName, "[LName]") // Map the Property/Column
    .Column(e => e.DateOfBirth, "[DOB]") // Map the Property/Column
    .DbType(e => e.DateOfBirth, DbType.DateTime2) // Defines the DatabaseType of the Property
    .ClassHandler<CustomerClassHandler>() // Defines the ClassHandler of the Class
    .PropertyHandler<CustomerAddressPropertyHandler>(e => e.Address); // Defines the PropertyHandler of the Property
    .PropertyValueAttributes<CustomerAddressPropertyHandler>(e => e.Address, new PropertyValueAttribute[]
    {
        new NameAttribute("Address"),
        new SizeAttribute(1024),
        new DbTypeAttribute(DbType.NVarChar)
    }); // Defines the PropertyHandler of the Property

To define mappings for a specific .NET CLR type, use the Type() method:

FluentMapper
    .Type<DateTime>() // Define which .NET CLR type
    .DbType(DbType.DateTime2) // Define the DatabaseType of the .NET CLR type
    .PropertyHandler<DateTimeKindToUtcPropertyHandler>(); // Define the PropertyHandler of the .NET CLR type

FluentMapper
    .Type<Microsoft.SqlServer.Types.SqlGeography>()
    .PropertyValueAttributes(new[]
    {
        new SqlDbTypeAttribute(SqlDbType.Udt),
        new UdtTypeNameAttribute("Geography")
    });

Mapping priority is determined first at the attribute level, then at the property level, then at the type level.

FluentMapper uses the following classes internally to establish mappings: ClassMapper, ClassHandlerMapper, IdentityMapper, PrimaryMapper, PropertyHandlerMapper, PropertyMapper, and TypeMapper.

Class Name Mapping

Use the ClassMapper class to map a class to its equivalent database object (table or view).

Given a Customer class with an equivalent table named Customer under the sales schema:

public class Customer
{
    public int Id { get; set; }
    public string FirstName { get; set;}
    public string LastName { get; set;}
    ...
}

Use the Add() method to map it:

ClassMapper.Add<Customer>("[sales].[Customer]");

To retrieve the mapped name, use the Get() method:

var mappedName = ClassMapper.Get<Customer>();

Use ClassMappedNameCache when retrieving the mapped name to maximize reusability and performance.

var mappedName = ClassMappedNameCache.Get<Customer>();

To remove the mapping, use the Remove() method:

ClassMapper.Remove<Customer>();

Identity Mapping

Use the IdentityMapper class to map a class property as an identity.

To add a mapping:

IdentityMapper.Add<Customer>(e => e.Id);

To retrieve the mapping (returns a ClassProperty instance):

var property = IdentityMapper.Get<Customer>();

Use IdentityCache when retrieving the identity property to maximize reusability and performance.

var property = IdentityCache.Get<Customer>();

To remove the mapping:

IdentityMapper.Remove<Customer>();

Primary Mapping

Use the PrimaryMapper class to map a class property as a primary key.

To add a mapping:

PrimaryMapper.Add<Customer>(e => e.Id);

To retrieve the mapping (returns a ClassProperty instance):

var property = PrimaryMapper.Get<Customer>();

Use PrimaryCache when retrieving the primary property to maximize reusability and performance.

var mappedName = PrimaryCache.Get<Customer>();

To remove the mapping:

PrimaryMapper.Remove<Customer>();

ClassHandler Mapping

Use the ClassHandlerMapper class to map a class handler to a .NET CLR type.

Given the following class handler:

public class CustomerClassHandler : IClassHandler<Customer>
{
    public Customer Get(Customer entity, DbDataReader reader)
    {
        return entity;
    }

    public Customer Set(Customer entity)
    {
        return entity;
    }
}

To add a mapping:

ClassHandlerMapper.Add<Customer, CustomerClassHandler>();

To retrieve the mapping:

var classHandler = ClassHandlerMapper.Get<Customer, CustomerClassHandler>();

Use ClassHandlerMapper when retrieving cached class handlers to maximize reusability and performance.

var classHandler = ClassHandlerCache.Get<Customer, CustomerClassHandler>();

To remove the mapping:

ClassHandlerMapper.Remove<Customer>();

PropertyHandler Mapping

Use the PropertyHandlerMapper class to map property handlers to a .NET CLR type or class property.

To map a property handler to an entity model property, given the following handler:

public class CustomerAddressPropertyHandler : IPropertyHandler<string, Address>
{
    public Address Get(string input, ClassProperty property)
    {
        return !string.IsNullOrEmpty(input) ? JsonConvert.Deserialize<Address>(input) : null;
    }

    public string Set(Address input, ClassProperty property)
    {
        return input != null ? JsonConvert.Serialize(input) : null;
    }
}

To add a mapping:

PropertyHandlerMapper.Add<Customer, CustomerAddressPropertyHandler>(e => e.Address);

To retrieve the mapping:

var propertyHandler = PropertyHandlerMapper.Get<Customer, CustomerAddressPropertyHandler>(e => e.Address);

Use PropertyHandlerCache when retrieving cached property handlers to maximize reusability and performance.

var propertyHandler = PropertyHandlerMapper.Get<Customer, CustomerAddressPropertyHandler>(e => e.Address);

To remove the mapping:

PropertyHandlerMapper.Remove<Customer>(e => e.Address);

To define a type-level property handler mapping for all System.DateTime properties, given the following handler:

public class DateTimeKindToUtcPropertyHandler : IPropertyHandler<datetime?, datetime?>
{
    public datetime? Get(datetime? input, ClassProperty property)
    {
        return input.HasValue ? DateTime.SpecifyKind(input.Value, Kind.Utc) : null;
    }

    public datetime? Set(datetime? input, ClassProperty property)
    {
        return input.HasValue ? DateTime.SpecifyKind(input.Value, Kind.Unspecified) : null;
    }
}

To add a type-level mapping:

PropertyHandlerMapper.Add<DateTime, DateTimeKindToUtcPropertyHandler>();

To retrieve the type-level mapping:

var propertyHandler = PropertyHandlerMapper.Get<DateTime>();

Use PropertyHandlerCache instead for better performance:

var propertyHandler = PropertyHandlerMapper.Get<DateTime>();

To remove the type-level mapping:

PropertyHandlerMapper.Remove<DateTime>();

Property Name Mapping

Use the PropertyMapper class to map class properties to their equivalent database columns.

Given the following Customer class:

public class Customer
{
    public int Id { get; set; }
    public string FirstName { get; set;}
    public string LastName { get; set;}
    public DateTime DateOfBirth { get; set;}
    ...
}

And the following [dbo].[Customer] table:

CREATE TABLE [dbo].[Customer]
(
	[Id] [bigint] IDENTITY(1,1) NOT NULL,
	[FName] [nvarchar](128) NOT NULL,
	[LName] [nvarchar](128) NOT NULL,
	[DOB] [datetime2](5) NOT NULL,
	[CreatedDateUtc] [datetime2](5) NOT NULL,
	CONSTRAINT [CRIX_Customer_Id] PRIMARY KEY CLUSTERED ([Id] ASC) ON [PRIMARY]
)
ON [PRIMARY];
GO

Use the Add() method to map the properties:

PropertyMapper.Add<Customer>(e => e.FirstName, "[FName]");
PropertyMapper.Add<Customer>(e => e.LastName, "[LName]");
PropertyMapper.Add<Customer>(e => e.DateOfBirth, "[DOB]");

To retrieve the mapped names:

var firstName = PropertyMapper.Get<Customer>(e => e.FirstName);
var lastName = PropertyMapper.Get<Customer>(e => e.LastName);
var dob = PropertyMapper.Get<Customer>(e => e.DateOfBirth);

Use PropertyMappedNameCache when retrieving cached mapped names to maximize reusability and performance.

var firstName = PropertyMappedNameCache.Get<Customer>(e => e.FirstName);
var lastName = PropertyMappedNameCache.Get<Customer>(e => e.LastName);
var dob = PropertyMappedNameCache.Get<Customer>(e => e.DateOfBirth);

To remove the mappings:

PropertyMapper.Remove<Customer>(e => e.FirstName);
PropertyMapper.Remove<Customer>(e => e.LastName);
PropertyMapper.Remove<Customer>(e => e.DateOfBirth);

Database Type Mapping

Use the TypeMapper class to map .NET CLR types or class properties to their equivalent database types.

Property Level

Given the following Customer class:

public class Customer
{
    public int Id { get; set; }
    ...
    public DateTime DateOfBirth { get; set; }
    ...
}

To map DateOfBirth to DbType.DateTime2:

TypeMapper.Add<Customer>(e => e.DateOfBirth, DbType.DateTime2);

To retrieve the mapping:

var dbType = TypeMapper.Get<Customer>(e => e.DateOfBirth);

Use TypeMapCache when retrieving cached database types to maximize reusability and performance.

var dbType = TypeMapCache.Get<Customer>(e => e.DateOfBirth);

To remove the mapping:

TypeMapper.Remove<Customer>(e => e.DateOfBirth);

Type Level

To map all System.DateTime values to DbType.DateTime2:

TypeMapper.Add<DateTime>(DbType.DateTime2);

To retrieve the mapping:

var dbType = TypeMapper.Get<DateTime>();

Use TypeMapCache instead for better performance:

var dbType = TypeMapCache.Get<DateTime>();

To remove the type-level mapping:

TypeMapper.Remove<DateTime>();

Please visit the Type Mapping feature for further information.

Property Value Attribute Mapping

Use the PropertyValueAttributeMapper class to manage property value attribute mappings.

To add a mapping:

PropertyValueAttributeMapper.Add<Customer>(e => e.FirstName, new NameAttribute("FName"));

Multiple attributes can be mapped at once:

PropertyValueAttributeMapper.Add<Customer>(e => e.FirstName, new PropertyValueAttribute[]
{
    new NameAttribute("FName"),
    new SizeAttribute(128),
    new DbTypeAttribute(DbType.AnsiString)
});

To retrieve the mapping:

var attributes = PropertyValueAttributeMapper.Get<Customer>(e => e.FirstName);

Use PropertyValueAttributeCache when retrieving cached property value attributes to maximize reusability and performance.

var attributes = PropertyValueAttributeCache.Get<Customer>(e => e.FirstName);

To remove the mapping:

PropertyValueAttributeMapper.Remove<Customer>(e => e.FirstName);

The force argument does not override attribute-based mappings (e.g., via System.ComponentModel.DataAnnotations.Schema (Table, Column), Map, Primary, Identity, TypeMap, ClassHandler and PropertyHandler).

In the Add() method of all mappers, an exception is thrown if the mapping already exists and the force argument was not set.