How to: Extend Fluent Models Using Code-Only Mapping
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.
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.
EntitiesModel domainModelContext = new EntitiesModel();
FluentModelMetadataSource fluentMetadata = new FluentModelMetadataSource( domainModelContext.Metadata );
FluentModelContext fluentModelContext = new FluentModelContext( fluentMetadata.GetModel() );
Dim domainModelContext As New EntitiesModel()
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