Data Access has been discontinued. Please refer to this page for more information.

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:

  1. Extending a Fluent Model with New Artificial Types
  2. Extending a Fluent Model with New CLR Types
  3. Modifying the FluentMetadataSource Class
  4. Extending the FluentModelContext
  5. 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