How to: Extend Fluent Models Using Code-Only Mapping
This topic demonstrates how to extend an existing fluent model with new types by using Code-Only Mapping:
- Extending a Fluent Model with New Artificial Types
- Extending a Fluent Model with New CLR Types
- Modifying the FluentMetadataSource Class
- Extending the FluentModelContext
- Creating a New FluentModelContext Instance
Extending a Fluent Model with New Artificial Types
This section shows how to extend the fluent model with new artificial types. Adding new artificial types to an existing fluent model is straight-forward. You can create the new artificial types in the PrepareMapping model. In the following example, a new artificial type named Employee is created.
MappingConfiguration employeeConfiguration = new MappingConfiguration( "Employee", "EmployeeNamespace" );
employeeConfiguration.HasArtificialPrimitiveProperty<int>( "Id" ).IsIdentity( KeyGenerator.Autoinc );
employeeConfiguration.HasArtificialStringProperty( "Name" );
employeeConfiguration.HasArtificialPrimitiveProperty<int>( "Age" );
Dim employeeConfiguration As New MappingConfiguration("Employee", "EmployeeNamespace")
employeeConfiguration.HasArtificialPrimitiveProperty(Of Integer)("Id").IsIdentity(KeyGenerator.Autoinc)
employeeConfiguration.HasArtificialStringProperty("Name")
employeeConfiguration.HasArtificialPrimitiveProperty(Of Integer)("Age")
Extending a Fluent Model with New CLR Types
This section demonstrates how to extend the fluent model with a new CLR type - the Person class. Again, in order to extend your fluent model with new CLR types, you have to create the mapping in the PrepareMapping method. The code is straight-forward. First a new instance of the MappingConfiguration<T> class is created. Next, by using the default mapping functionality, the Person type is mapped. For more information, check out the Mapping CLR Types section.
MappingConfiguration<Person> personConfiguration = new MappingConfiguration<Person>();
personConfiguration.MapType( p => new
{
PersonId = p.Id,
LastName = p.LastName,
FirstName = p.FirstName,
Contact = p.Address
} ).ToTable( "People" );
personConfiguration.HasProperty( p => p.Id ).IsIdentity( KeyGenerator.Autoinc );
Dim personConfiguration As New MappingConfiguration(Of Person)()
personConfiguration.MapType(Function(p) New With {Key .PersonId = p.Id,
Key .LastName = p.LastName,
Key .FirstName = p.FirstName,
Key .Contact = p.Address}).ToTable("People")
personConfiguration.HasProperty(Function(p) p.Id).IsIdentity(KeyGenerator.Autoinc)
personConfiguration.FieldNamingRules.AddPrefix = "_"
Modifying the FluentMetadataSource Class
Basically, in this scenario, you are going to mix Code-Only Mapping API and Fluent Model. In other words, you are going to combine two mapping sources. The FluentMetadataSource class exposes a constructor that allows you initializes a new instance of the FluentMetadataSource class with an existing metadata container, i.e. the fluent model metadata. There is one very important note that should be pointed here: the MyFluentMetadataSource class defines a constructor accepting a MetadataContainer instance. You will have to pass the MetadataContainer that describes the existing fluent model.
Having this in mind, here's a sample implementation of the FluentMetadataSource class:
public class FluentModelMetadataSource : FluentMetadataSource
{
public FluentModelMetadataSource()
{
}
public FluentModelMetadataSource( MetadataContainer existingModel ) :
base( existingModel )
{
}
protected override IList<MappingConfiguration> PrepareMapping()
{
List<MappingConfiguration> configurations = new List<MappingConfiguration>();
MappingConfiguration employeeConfiguration =
new MappingConfiguration( "Employee", "EmployeeNamespace" );
employeeConfiguration.HasArtificialPrimitiveProperty<int>( "Id" ).
IsIdentity( KeyGenerator.Autoinc );
employeeConfiguration.HasArtificialStringProperty( "Name" );
employeeConfiguration.HasArtificialPrimitiveProperty<int>( "Age" );
MappingConfiguration<Person> personConfiguration = new MappingConfiguration<Person>();
personConfiguration.MapType( p => new
{
PersonId = p.Id,
LastName = p.LastName,
FirstName = p.FirstName,
Contact = p.Address
} ).ToTable( "People" );
personConfiguration.HasProperty( p => p.Id ).IsIdentity( KeyGenerator.Autoinc );
configurations.Add( employeeConfiguration );
configurations.Add( personConfiguration );
return configurations;
}
}
Public Class FluentModelMetadataSource
Inherits FluentMetadataSource
Public Sub New()
End Sub
Public Sub New(ByVal existingModel As MetadataContainer)
MyBase.New(existingModel)
End Sub
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 employeeConfiguration As New MappingConfiguration("Employee", "EmployeeNamespace")
employeeConfiguration.HasArtificialPrimitiveProperty(Of Integer)("Id"). _
IsIdentity(KeyGenerator.Autoinc)
employeeConfiguration.HasArtificialStringProperty("Name")
employeeConfiguration.HasArtificialPrimitiveProperty(Of Integer)("Age")
Dim personConfiguration As New MappingConfiguration(Of Person)()
personConfiguration.MapType(Function(p) New With {Key .PersonId = p.Id,
Key .LastName = p.LastName,
Key .FirstName = p.FirstName,
Key .Contact = p.Address}).ToTable("People")
personConfiguration.HasProperty(Function(p) p.Id).IsIdentity(KeyGenerator.Autoinc)
personConfiguration.FieldNamingRules.AddPrefix = "_"
configurations.Add(employeeConfiguration)
configurations.Add(personConfiguration)
Return configurations
End Function
End Class
The FluentModelMetadataSource class must provide parameterless constructor.
Extending the FluentModelContext
Next, you need to add a constructor in the FluentModelContext class that accept a MetadataContainers instance. For example:
public FluentModelContext(MetadataContainer fluentContainer)
: base( DbConnection, backendConfiguration, fluentContainer )
{
}
Public Sub New(ByVal fluentContainer As MetadataContainer)
MyBase.New(DbConnection, backendConfiguration, fluentContainer)
End Sub
Creating a New FluentModelContext Instance
The following example demonstrates how to create a new instance of the FluentModelContext by using the metadata container of the fluent model.
FluentModel domainModelContext = new FluentModel();
FluentModelMetadataSource fluentMetadata = new FluentModelMetadataSource( domainModelContext.Metadata );
FluentModelContext fluentModelContext = new FluentModelContext( fluentMetadata.GetModel() );
Dim domainModelContext As New FluentModel()
Dim fluentMetadata As New FluentModelMetadataSource(domainModelContext.Metadata)
Dim _fluentModelContext As New FluentModelContext(fluentMetadata.GetModel())
Person Class
public class Person
{
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
public string Address {get;set;}
}
Public Class Person
Private _id As Integer
Public Property Id() As Integer
Get
Return _id
End Get
Set(ByVal value As Integer)
_id = value
End Set
End Property
Private _firstName As String
Public Property FirstName() As String
Get
Return _firstName
End Get
Set(ByVal value As String)
_firstName = value
End Set
End Property
Private _lastName As String
Public Property LastName() As String
Get
Return _lastName
End Get
Set(ByVal value As String)
_lastName = value
End Set
End Property
Private _address As String
Public Property Address() As String
Get
Return _address
End Get
Set(ByVal value As String)
_address = value
End Set
End Property
End Class