Link Search Menu Expand Document

Implicit Mapping


This is a feature that would allow you to implicitly map the .NET CLR types or class properties into its equivalent object in the database. Certain mapper classes has been provided in order to avoid the usage of the attributes within the classes.

Fluent Mapping

Use the FluentMapper class to fluently manage the mappings of the table/properties, primary/identity columns, database types and class/property handlers.

Below is the code to define the mappings for an entity property, 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

Below is the code on how to define the mappings for a specfic .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")
    });

The priority of the mapping is first identified via an attribute-level, then followed by a property-level and lastly by a type-level.

The FluentMapper is using the following classes (ClassMapper, ClassHandlerMapper, IdentityMapper, PrimaryMapper, PropertyHandlerMapper, PropertyMapper and TypeMapper) underneath to establish the proper mappings.

Class Name Mapping

Use the ClassMapper class to manage the mappings of the class into its equivalent object in the database (i.e.: Table, View).

Let us say you have a Customer class which has an equivalent table named Customer under sales schema.

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

Then, 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>();

We recommend to use the ClassMappedNameCache class when retrieving the mapped name. This is to maximize the 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 manage the mappings of the class property as an identity.

To add a mapping, use the Add() method.

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

To retrieve the mapping, use the Get() method. The method returns an instance of ClassProperty object.

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

We recommend to use the IdentityCache class when retrieving the identity property. This is to maximize the reusability and performance.

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

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

IdentityMapper.Remove<Customer>();

Primary Mapping

Use the PrimaryMapper class to manage the mappings of the class property as a primary.

To add a mapping, use the Add() method.

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

To retrieve the mapping, use the Get() method. The method returns an instance of ClassProperty object.

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

We recommend to use the PrimaryCache class when retrieving the primary property. This is to maximize the reusability and performance.

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

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

PrimaryMapper.Remove<Customer>();

ClassHandler Mapping

Use the ClassHandlerMapper class to manage the mappings of the .NET CLR type class handler.

Let us say you have class handler below.

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, use the Add() method.

ClassHandlerMapper.Add<Customer, CustomerClassHandler>();

To retrieve the mapping, use the Get() method.

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

We recommend to use the ClassHandlerCache class when retrieving the cached class handlers. This is to maximize the reusability and performance.

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

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

ClassHandlerMapper.Remove<Customer>();

PropertyHandler Mapping

Use the PropertyHandlerMapper class to manage the mappings between the property handlers and the .NET CLR type or class property.

Below is the code on how to map a property hanlder on an entity model property. Let us say you have property handler below.

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, use the Add() method.

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

To retrieve the mapping, use the Get() method.

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

We recommend to use the PropertyHandlerCache class when retrieving the cached property handlers. This is to maximize the reusability and performance.

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

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

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

Below is a code on how to define a property handler mapping in a type level. Let us say you want to handle all the System.DateTime properties and you have created the property handler below.

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 mapping, use the type-level Add() method.

PropertyHandlerMapper.Add<DateTime, DateTimeKindToUtcPropertyHandler>();

To retrieve the mapping, use the type-level Get() method.

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

Same here, we highly recommend to use the PropertyHandlerCache class instead.

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

To remove the mapping, use the type-level Remove() method.

PropertyHandlerMapper.Remove<DateTime>();

Property Name Mapping

Use the PropertyMapper class to manage the mappings of the class property into its equivalent column in the database.

Let us say you have the Customer class below.

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 [dbo].[Customer] table below.

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

Then, use the Add() method to map it.

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 name, use the Get() method.

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

We recommend to use the PropertyMappedNameCache class when retrieving the cached mapped name. This is to maximize the 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 mapping, use the Remove() method.

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 manage the mappings of the .NET CLR type or class property into its equivalent database type.

Property Level

Let us say you have the Customer class below.

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

And you would like to map the property of the DateOfBirth property into DbType.DateTime2 database type.

Then, use the Add() method to map it.

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

To retrieve the mapping, use the Get() method.

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

We recommend to use the TypeMapCache class when retrieving the cached database types. This is to maximize the reusability and performance.

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

To remove the mapping, ue the Remove() method.

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

Type Level

Let us say you would like to always map the System.DateTime .NET CLR type equivalent to DbType.DateTime2 database type.

Then, use the type-level mapping via Add() method.

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

To retrieve the mapping, use the type-level Get() method.

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

Same here, we highly recommend to use the TypeMapCache class instead.

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

To remove the mapping, use the type-level Remove() method.

TypeMapper.Remove<DateTime>();

Please visit the Type Mapping feature for further information.

Property Value Attribute Mapping

Use the PropertyValueAttributeMapper class to manage the mappings of the property value attributes.

Let us say you have class handler below.

To add a mapping, use the Add() method.

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

You can also map a multiple instances.

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

To retrieve the mapping, use the Get() method.

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

We recommend to use the PropertyValueAttributeCache class when retrieving the cached property value attributes. This is to maximize the reusability and performance.

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

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

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

Please be noted that the force argument is not overriding that attribute-based mapping (i.e.: by using the System.ComponentModel.DataAnnotations.Schema (Table, Column), Map, Primary, Identity, TypeMap, ClassHandler and PropertyHandler).

In the Add() method of all mappers, an exception will be thrown if the mapping is already exists and if you did not enfored the call using the force argument.