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

How to: Customize Collections in Fluent Models (C#)

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 applies to C# only. In order to modify collection generation in VB.NET Fluent Models, please refer to How to: Customize Collections in Fluent Models (VB).

By default, when you create a new domain model all collections are generated in the following manner:

public partial class Category
{
   private IList<Car> _cars = new List<Car>();
   public virtual IList<Car> Cars
   {
       get
       {
           return this._cars;
       }
   }
}

However, in data-binding scenarios you may need to use other types of collections.

This example demonstrates how to modify the default code generation templates so that the navigation properties are of type TrackedList<T> or TrackedBindingList<T> instead of List<T>.

TrackedList<T> and TrackedBindingList<T> can be found in the Telerik.OpenAccess namespace and are used by Telerik Data Access to monitor the changes in the content of the navigation properties.

The process includes the following steps:

  1. Preparation of the project that holds the domain model
  2. Preparation of the templates
  3. Custom changes in the templates
  4. Apply the modified templates

1. Preparation of the project that holds the domain model

  • Create an empty class library project and add a new folder named OpenAccessTemplates in it.

  • From <install-dir>\dsl20XX\CodeGenerationTemplates\CSharp\ copy the necessary templates in the OpenAccessTemplates folder and include them in the project:

    • The Includes_ver.2 folder
      • AttributesGenerator.ttinclude
      • ClassGenerator.ttinclude
      • ContextGenerator.ttinclude
      • DocumentationGenerator.ttinclude
      • DomainMethodsGenerator.ttinclude
      • Engine.ttinclude
      • FluentMappingGenerator.ttinclude
      • InterfacesGenerator.ttinclude
      • NamespacesGenerator.ttinclude
      • PropertiesGenerator.ttinclude
      • Template.ttinclude
      • UsingsGenerator.ttinclude
    • From <install-dir>\dsl20XX\CodeGenerationTemplates\FluentMapping\CSharp\ copy the FluentModel.tt file.

The OpenAccessTemplates folder should contain the FluentModel.tt file and an Includes_ver.2 subfolder with twelve .ttinclude files.

2. Preparation of the templates

Once the templates are included in your project, you will notice that Error List in Visual Studio will notify you of some errors. They occur because the templates delivered by Telerik Data Access require additional steps performed by its tools. In order to avoid them you need to do the following:

  • Delete the .cs file under the FluentModel.tt file
  • Delete the content of the Custom Tool property for the FluentModel.tt file

3. Custom changes in the templates

At this stage you are ready to perform the necessary custom changes in the templates:

  • Open PropertiesGenerator.ttinclude
  • Place the following code at the end of the GenerateFieldForProperty() method:

    if (property.IsNavigationProperty && property.IsIEnumerable)
    {
        propertyType = "TrackedList<" + property.Type + ">";
        initialValue = " = new " + propertyType + "()";
    }
    
  • Place the following code at the end of the GenerateClassPropertySignature() method:

    if (property.IsNavigationProperty && property.IsIEnumerable)
    {
        propertyType = "TrackedList<" + property.Type + ">";
    }
    
  • Open FluentMappingGenerator.ttinclude

  • Replace the GetHasAssociationToken() method with the following:

    private string GetHasAssociationToken(MetaNavigationMember navigationMember)
    {
        MetaAssociation association = navigationMember.Association;
        if(association == null)
        {
            throw new ArgumentException("navigationMember");
        }
        MetaNavigationMember opositeMember = navigationMember.GetOppositeMember();
        string opositeType = string.Empty;
        if(opositeMember != null && opositeMember.DeclaringType != null && opositeMember.IsVisible )
        {
            string typeName = opositeMember.DeclaringType.Name;
            if(string.Equals(opositeMember.DeclaringType.Namespace, opositeMember.DeclaringType.Name))
            {
                typeName = string.Concat(opositeMember.DeclaringType.Namespace, ".", opositeMember.DeclaringType.Name);
            }
            opositeType = string.Format("<{0}>", typeName);
        }
        string hasAssociationToken = string.Format(@".HasAssociation{0}(x => x.{1})",
            opositeType, navigationMember.PropertyName);
        return hasAssociationToken;
    }
    
  • In GenerateAssociationConfiguration(), replace the call to the GetHasAssociationToketn() method with the following:

    string hasAssociationToken = this.GetHasAssociationToken(navigationMember);
    

For TrackedBindingList<T> you only need to changed propertyType in the above code snippets.

4. Apply the modified templates

Right-click on the name of the class library project and select Add/New Item... to run the Add New Item dialogue. Select the Telerik Data Access Fluent Model item template to run the Create Model wizard. The necessary settings are on the Code Generation Settings page in the Advanced Options dialogue.

The process is as follows:

  • Navigate to the Advanced Options dialogue of the Create Model wizard or open the Code Generation Settings tab in Model Settings.
  • In the Code Generation Template section check the Custom Defined radio-button and click Browse...
  • Navigate to the OpenAccessTemplates folder, select FluentModel.tt and click OK to close the Open dialogue

  • Click Finish

The outcome should be similar to this one:

public partial class Category
{
   private TrackedList<Car> _cars = new TrackedList<Car>();
   public virtual TrackedList<Car> Cars
   {
       get
       {
           return this._cars;
       }
   }
}

In the cases when your project is tracked by a source control system, we recommend that the whole OpenAccessTemplates folder is checked-in with it. That allows the entire team to work with the hosting project without any risk for the changes in the templates or in the generated service files to be rewritten.