Using Per-Class Configuration
This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.
The Fluent Mapping API allows you to map your classes by creating a static method that returns a MappingConfiguration in the respective class. When you use per-class configuration, you still need to create a class that derives from FluentMetadataSource and to override the abstract PrepareMapping method. The PrepareMapping method should just return an empty list. With this setup, during runtime the mapping will be collected from all of the classes having a static method that returns a MappingConfiguration.
Using Per-Class Configuration
The following example demonstrates you how to map the Person entity:
public class Person
{
public int Id {get;set;}
public string FirstName {get;set;}
public static MappingConfiguration GetMapping()
{
MappingConfiguration<Person> person = new MappingConfiguration<Person>();
person.MapType( p => new
{
Id = p.Id,
FirstName = p.FirstName
} ).ToTable( "People" );
person.HasProperty( p => p.Id ).IsIdentity();
return person;
}
}
Public Class Person
Private _id As Integer
Public Property Id As Integer
Get
Return _id
End Get
Set(value As Integer)
_id = value
End Set
End Property
Private _firstName As String
Public Property FirstName As String
Get
Return _firstName
End Get
Set(value As String)
_firstName = value
End Set
End Property
Public Shared Function GetMapping() As MappingConfiguration
Dim person As New MappingConfiguration(Of Person)()
person.MapType(Function(p) New With {Key .Id = p.Id,
Key .FirstName = p.FirstName}).ToTable("People")
person.FieldNamingRules.AddPrefix = "_"
person.HasProperty(Function(p) p.Id).IsIdentity()
Return person
End Function
End Class
Also, when you use a per-class configuration, you can provide a configuration for the private members of the class. This is something that's not achievable when you provide a mapping in the PrepareMapping method.
public class Person
{
private string lastName;
public int Id {get;set;}
public string FirstName {get;set;}
public static MappingConfiguration GetMapping()
{
MappingConfiguration<Person> person = new MappingConfiguration<Person>();
person.MapType( p => new
{
Id = p.Id,
FirstName = p.FirstName,
LastName = p.lastName
} ).ToTable( "People" );
person.HasProperty( p => p.Id ).IsIdentity();
return person;
}
}
Public Class Person
Private _lastName As String
Private _id As Integer
Public Property Id As Integer
Get
Return _id
End Get
Set(value As Integer)
_id = value
End Set
End Property
Private _firstName As String
Public Property FirstName As String
Get
Return _firstName
End Get
Set(value As String)
_firstName = value
End Set
End Property
Public Shared Function GetMapping() As MappingConfiguration
Dim person As New MappingConfiguration(Of Person)()
person.MapType(Function(p) New With {Key .Id = p.Id,
Key .FirstName = p.FirstName,
Key .LastName = p._lastName}).ToTable("People")
person.FieldNamingRules.AddPrefix = "_"
person.HasProperty(Function(p) p.Id).IsIdentity()
Return person
End Function
End Class
Using Per-Class Configuration and the PrepareMapping Method
An interesting case is when you have a per-class configuration, a custom FluentMetadataSource, and you provide a mapping configuration for the target class in both of the places. In this case a higher priority will have the mapping in the PrepareMapping method. All other property (fields) mappings which are not provided in the PrepareMapping method will be taken from the static method provided by the class. Note that in this case, any additional mapping configurations in the static method will be skipped. In the following example, you have a custom FluentMetadataSource, where you provide a mapping configuration for the Person class.
public class FluentModelMetadataSource : FluentMetadataSource
{
protected override IList<MappingConfiguration> PrepareMapping()
{
List<MappingConfiguration> configurations = new List<MappingConfiguration>();
MappingConfiguration<Person> personConfiguration = new MappingConfiguration<Person>();
personConfiguration.MapType(p => new
{
Address = p.Address,
LastName = p.LastName
}).ToTable("People");
configurations.Add( personConfiguration );
return configurations;
}
}
Public Class FluentModelMetadataSource
Inherits FluentMetadataSource
Protected Overrides Function PrepareMapping() As _
System.Collections.Generic.IList(Of Telerik.OpenAccess.Metadata.Fluent.MappingConfiguration)
Dim configurations As List(Of MappingConfiguration) = New List(Of MappingConfiguration)()
Dim personConfiguration As New MappingConfiguration(Of Person)()
personConfiguration.MapType(Function(p) New With {Key .Address = p.Address,
Key .LastName = p.LastName}).ToTable("People")
personConfiguration.FieldNamingRules.AddPrefix = "_"
configurations.Add(personConfiguration)
Return configurations
End Function
End Class
At the same time you have a static method creating MappingConfiguration in the Person class.
public class Person
{
public string LastName { get; set; }
public int Id {get;set;}
public string FirstName {get;set;}
public string Address { get; set; }
public static MappingConfiguration GetMapping()
{
MappingConfiguration<Person> person = new MappingConfiguration<Person>();
person.MapType( p => new
{
Id = p.Id,
FirstName = p.FirstName
} ).ToTable( "People" );
person.HasProperty( p => p.Id ).IsIdentity();
return person;
}
}
Public Class Person
Private _lastName As String
Public Property LastName As String
Get
Return _lastName
End Get
Set(value As String)
_lastName = value
End Set
End Property
Private _id As Integer
Public Property Id As Integer
Get
Return _id
End Get
Set(value As Integer)
_id = value
End Set
End Property
Private _firstName As String
Public Property FirstName As String
Get
Return _firstName
End Get
Set(value As String)
_firstName = value
End Set
End Property
Private _address As String
Public Property Address As String
Get
Return _address
End Get
Set(value As String)
_address = value
End Set
End Property
Public Shared Function GetMapping() As MappingConfiguration
Dim person As New MappingConfiguration(Of Person)()
person.MapType(Function(p) New With {Key .Id = p.Id,
Key .FirstName = p.FirstName}).ToTable("People")
person.FieldNamingRules.AddPrefix = "_"
person.HasProperty(Function(p) p.Id).IsIdentity()
Return person
End Function
End Class
Several notes should be pointed for the last two code-snippets:
- First, property configurations for the Address and LastName properties are created in the PrepareMapping method.
- Second, property configurations for the Id and FirstName properties are created in the static GetMapping method.
- The Id property is set as an identity field in the static GetMapping method.
In this case the Fluent Mapping API will take a look first at the PrepareMapping method - it will take the property configurations for the Address and LastName properties from there. Next, the static GetMapping method will be processed and information about the Id and FirstName configuration will be retrieved. However, the identity configuration for the Id property will be skipped by the Fluent Mapping API, because of these two reasons:
- First, you are providing mapping for the Person object in the PrepareMapping method and for the static GetMapping method at the same time.
- Second, the IsIdentity configuration is performed in the static GetMapping method.
For example, if you set the Id property as an identity field in the PrepareMapping method, then this instruction will be processed by the Fluent Mapping API. Also, if you set the Id property as an identity field in the static GetMapping method, but at the same time you don't provide a configuration for the Person class in the PrepareMapping, then the IsIdentity configuration for the Id property will be processed again. In summary, if you provide mapping for the same object in both of the places, then any additional property configurations in the static method will be skipped.
Another case that should be considered is when you provide a mapping configuration for the same property in both of the places. In this case an exception will be thrown.