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

Code Only Scenario

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 Telerik Data Access Visual Designer is designed to help you build Telerik Data Access applications. With the Visual Designer you can create a domain model from an existing database and then graphically visualize and edit your domain model. Or, you can graphically create a domain model first, and then generate a database that supports your model. In either case, you can automatically update your model when the underlying database changes and automatically generate object-layer code for your application.

However, many developers view their code as their model. Ideally these developers just want to write some class and without ever touching a designer or a piece of XML to be able to use those classes with Telerik Data Access. Basically they want to write "Code Only". Fortunately, Telerik Data Access provides a Fluent Mapping API, which is perfect for these scenarios. This topic will introduce you with the Telerik Data Access Fluent Mapping API.

Creating the Project

To create a new Telerik Data Access domain model using the Fluent Mapping API:

  1. Select File > New Project in Visual Studio.
  2. In the list of Installed Templates on the left side of the dialog, select Visual C# or Visual Basic.
  3. Then select Telerik Data Access Fluent Library. Name the project FluentModel, and then click OK.

  4. This template works in the same way as the Telerik Data Access Class Library project template, which is discussed in the Database First Scenario and Model First Scenario topics. The template will create a new class library project and will run the Telerik Data Access New Model Wizard. However, it will create a new model (from an existing database or an empty one) by using the fluent mapping code generation. The first step in the wizard lets you choose the type of model you want to use. In this step, you have the option of generating a model from a database or starting with an empty model. In this article, you will manually create all fluent classes, so select the Empty fluent model option as shown on the figure below.

  5. Click Finish to generate the model.

What Just Happened?

When you click OK, the template will create a new project and will enhance it to work with Telerik Data Access. In addition, it will add the required references and will add several code files.

What Are These Files?

Open the FluentModelMetadataSource class. It derives from the abstract Telerik.OpenAccess.Metadata.Fluent.FluentMetadataSource class. It will serve as a mapping source that uses fluent configuration to create a mapping model. You have to override the abstract PrepareMapping method (its implementation will be described later). The PrepareMapping method will be your entry point for working with the Telerik Data Access FluentMapping API. It is called when the context instance is initializing and a model needs to be obtained. Or in other words the new FluentMetadataSource class will hold the entire configuration for your classes.

Important: The custom FluentMetadataSource class and your POCO classes must be located in the same project.

When you use Fluent Mapping API, your classes have no knowledge about the Telerik Data Access at all. This is a good thing, as it is the desired effect. However, you need to let Telerik Data Access be aware of the classes. Recall that the Telerik Data Access New Domain Model Wizard does not only create the entity classes, but also creates a class that inherits from OpenAccessContext. Of course without code generation no OpenAccessContext is generated for you. To implement a context that is specific to your model and your entities, you simply create a new class that derives from OpenAccessContext and provides properties of type IQueryable<T>.

Open and explore the FluentModel class. The class derives from the OpenAccessContext class. Your FluentModel needs to be connected to the underlying database just like a generated context. To do this, you pass two things to the constructor. First, you pass a connection string to the underlying database. The second parameter is a new instance of the BackendConfiguration class where you specify the backend to be used (in this example - MS SQL database). Another thing you have pay attention to is that there is a third parameter passed to the base constructor - this is an instance of the FluentMetadataSource class that holds the entire configuration for your classes.

Take a look at the declaration of the connection string.

private static string connectionStringName = @"";
Private Shared connectionStringName As String = ""

You are passing a connection string name to the base constructor (not the real connection string). The real connection string is defined in the configuration file (App.config).

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <connectionStrings>
   <add name="connectionId" 
        connectionString="data source=.\sqlexpress;initial catalog=FluentMappingDatabase;
                          integrated security=True" 
        providerName="System.Data.SqlClient" />
 </connectionStrings>
</configuration>

You need to pass the same connection string name to the FluentModel constructor as the one defined in the configuration file, i.e., you need to pass "connectionId". Modify the connection string declaration in the FluentModel class and set the same name:

private static string connectionStringName = @"connectionId";
Private Shared connectionStringName As String = "connectionId"

Building the Model

You are ready to add code.

  1. Expand the solution explorer.
  2. Add a new class named Customer in the FluentModel project and paste in the code below. This code creates a simple customer class that can be mapped to a database table by Telerik Data Access.

    public class Customer
    {
       public int ID { get; set; }
       public string Name { get; set; }
       public DateTime DateCreated { get; set; }
       public string EmailAddress { get; set; }
    }
    
    Public Class Customer
        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 _name As String
        Public Property Name() As String
            Get
                Return _name
            End Get
            Set(ByVal value As String)
                _name = value
            End Set
        End Property
        Private _dateCreated As Date
        Public Property DateCreated() As Date
            Get
                Return _dateCreated
            End Get
            Set(ByVal value As Date)
                _dateCreated = value
            End Set
        End Property
        Private _emailAddress As String
        Public Property EmailAddress() As String
            Get
                Return _emailAddress
            End Get
            Set(ByVal value As String)
                _emailAddress = value
            End Set
        End Property
    End Class
    
  3. Next, open FluentModelMetadataSource.cs, and replace the existing code for the PrepareMapping method with this one. This code configures passes an anonymous type to the MapType method. The properties of the anonymous type will be what Telerik Data Access uses to create columns in the database. The ToTable method tells Telerik Data Access what the customer table should be named in the database.

    protected override IList<MappingConfiguration> PrepareMapping()
    {
       List<MappingConfiguration> configurations = new List<MappingConfiguration>();
    
       var customerMapping = new MappingConfiguration<Customer>();
       customerMapping.MapType(customer => new
       {
           ID = customer.ID,
           Name = customer.Name,
           EmailAddress = customer.EmailAddress,
           DateCreated = customer.DateCreated
       }).ToTable("Customer");
       customerMapping.HasProperty(c => c.ID).IsIdentity();
    
       configurations.Add(customerMapping);
    
       return configurations;
    }
    
    Protected Overrides Function PrepareMapping() As System.Collections.Generic.IList(Of MappingConfiguration)
        Dim configurations As New List(Of MappingConfiguration)()
        Dim customerMapping = New MappingConfiguration(Of Customer)()
    
        customerMapping.MapType(Function(customer) New With {
                                        Key .ID = customer.Id,
                                        Key .Name = customer.Name,
                                        Key .EmailAddress = customer.EmailAddress,
                                        Key .DateCreated = customer.DateCreated}).ToTable("Customer")
        customerMapping.FieldNamingRules.AddPrefix = "_"
    
        customerMapping.HasProperty(Function(p) p.Id).IsIdentity()
    
        configurations.Add(customerMapping)
        Return configurations
    End Function
    
  4. Open FluentModel.cs, add a property exposing the Customers collection. The code below exposes the Customer objects as an IQueryable<Customer> this allows Telerik Data Access to offload queries to the database to do the heavy lifting. It also makes it easy to query entity sets using standard LINQ.

    public IQueryable<Customer> Customers
    {
       get
       {
           return this.GetAll<Customer>();
       }
    }
    
    Public ReadOnly Property Customers() As IQueryable(Of Customer)
        Get
            Return Me.GetAll(Of Customer)()
        End Get
    End Property
    
  5. At this point the model is fully configured.

Deploying the Database

You need a project that will consume your data project. You might be asking why you created a separated project for your classes. The answer is simply because you want to compile your classes into a separate and distinct assembly from the UI project.

  1. For the sake of simplicity, add to your solution a new Console Application. For example, name the project FluentModelClient.

  2. Make the FluentModelClient project a startup project (right click on the ConsoleApplication in Solution Explorer, and select Set as StartUp Project).

  3. Add references to:

    1. Telerik.OpenAccess.dll
    2. Telerik.OpenAccess.35.Extensions.dll
    3. The model project, in the case of this guide - FluentModel.
  4. Copy the App.Config file from the FluentModel project and paste it in the FluentModelClient project. The reason for that action is that the FluentModelClient project is the main (executable) project for the application. When you run the application all settings (configurations) are taken from that project. Respectively, the OpenAccessContext will try to retreive the connection string from the config file in the main project. If a such doesn't exist, the initialization of the OpenAccessContext will fail.

  5. Open Program.cs in the Console Application. Add the following code for initializing the database.

    using Telerik.OpenAccess;
    
    namespace FluentModelClient
    {
       class Program
       {
           static void Main(string[] args)
           {
               UpdateDatabase();
           }
    
           private static void UpdateDatabase()
           {
               using (var context = new FluentModel.FluentModel())
               {
                   var schemaHandler = context.GetSchemaHandler();
                   EnsureDB(schemaHandler);
               }
           }
    
           private static void EnsureDB(ISchemaHandler schemaHandler)
           {
               string script = null;
               if (schemaHandler.DatabaseExists())
               {
                   script = schemaHandler.CreateUpdateDDLScript(null);
               }
               else
               {
                   schemaHandler.CreateDatabase();
                   script = schemaHandler.CreateDDLScript();
               }
    
               if (!string.IsNullOrEmpty(script))
               {
                   schemaHandler.ExecuteDDLScript(script);
               }
           }
       }
    }
    
    Imports Telerik.OpenAccess
    Module Module1
        Sub Main()
            UpdateDatabase()
        End Sub
    
        Private Sub UpdateDatabase()
            Using context = New FluentModel.FluentModel()
                Dim schemaHandler = context.GetSchemaHandler()
                EnsureDB(schemaHandler)
            End Using
        End Sub
    
        Private Sub EnsureDB(ByVal schemaHandler As ISchemaHandler)
            Dim script As String = Nothing
    
            If schemaHandler.DatabaseExists() Then
                script = schemaHandler.CreateUpdateDDLScript(Nothing)
            Else
                schemaHandler.CreateDatabase()
                script = schemaHandler.CreateDDLScript()
            End If
    
            If Not String.IsNullOrEmpty(script) Then
                schemaHandler.ExecuteDDLScript(script)
            End If
        End Sub
    End Module
    

    This code creates a new instance of the OpenAccessContext created when building the model using the Fluent Mapping API. It then checks to see if the database exists, if not the database is created, and then the schema is applied. If the database already exists, Telerik Data Access will create and run a migration script against the database. At this point when you run the application Telerik Data Access will update the database based on any changes made in the fluent mapping.

Next Steps

For more information, check out the Code-Only section.