T4 Templates and the Entity Framework

Scott Allen

Published: January 2011

Download the sample project for this article (C#, VS2010)

Code generation isn’t new in Visual Studio. Nearly every visual design surface, from Web Forms to Windows Forms to typed DataSet designers, has transformed shapes into code using code generation behind the scenes. The key phrase is behind the scenes. As developers, we did not always have the control we needed over the code generation process. What is new in Visual Studio is how more frameworks are using T4 Templates for code generation. The frameworks integrating with T4 can give developers complete control over the code generation process. The Entity Framework is one such framework.

This paper will discuss how the Entity Framework uses T4 Templates to generate custom code from an ADO.NET Entity Data Model (EDM), and assumes the reader is already familiar with the Entity Framework’s API and designer. We’ll begin with an overview of the T4 technology and see how the technology works. We’ll also look at how we can programmatically consume metadata from an EDM. In the end, we’ll combine these two pieces of knowledge to customize a T4 template.

What Are T4 Templates?

T4 is a general-purpose templating engine you can use to generate C# code, Visual Basic code, XML, HTML, or text of any kind. The first step in using T4 is to create a template file, which is a mix of literal text, code, and processing directives. The T4 template processor will transform this file into a text file of the desired type by executing the code and processing directives inside. As an example, you can right-click on any project in Visual Studio 2010 and add a new item of type Text Template.

Add new Text Template

Notice how a T4 template file uses an extension of .tt by default. You can add templates to any type of Visual Studio project – console applications, class libraries, ASP.NET, or WPF. If you look at the properties on a newly added template file in Solution Explorer, you’ll see the Custom Tool property is set to TextTemplatingFileGenerator. This custom tool is the template processor. The processor transforms the template file into a textual output file. In the following figure, we’ve added a template named Simple.tt.

Project with new template

The simplest possible content for Simple.tt might look like the following.

<#@ output extension=".txt" #>

This content was generated from a template

The first line of the file is a directive. Directives give instructions to the template processing engine on how to process, or transform the file. In this example, the directive tells the engine to generate a file with a .txt extension (a text file you can open with Notepad). The last line of the template file is literal text. The template processor will put literal text directly into the output file. In this example, the output is:

This content was generated from a template

The output is not exciting, but it gives us an idea of how templates work, and we’ll look at more complicated scenarios in just a bit. For now, let’s look at when the transformation takes place, and where the results live.

Transformation

There are a number of options available for template processing. One option is to process a template while your application is running. Runtime execution of a template means you could use T4 to generate form letters or HTML output. However, in this example we are using a more common T4 strategy and allowing the custom tool (TextTemplatingFileGenerator) to transform the template before the project even compiles.

Looking at the template in the Solution Explorer window, you’ll see Simple.tt is a tree node you can expand to reveal a file “behind” the template.

Viewing the file 'behind' the template

In this example, the output file is Simple.txt. By default, the generated file will have the same name as the template, but with a different extension (as specified in a processing directive).

If we could only use literal text inside of a template, then T4 would be a wholly unremarkable technology. Fortunately, we can also place executable code inside a template. Let’s change Simple.tt to use the following content:

<#@ template language="C#" #>
<#@ output extension=".txt" #>

This content was generated from a template
in the year <#= DateTime.Now.Year.ToString() #>

When we save the template, the processor will execute and place the following output into Simple.txt:

This content was generated from a template
in the year 2010

The <#= #> syntax allows us to inject dynamic text into the output using a C# expression. If you’ve ever worked with ASPX files in an ASP.NET project, then this syntax will feel familiar. I hope this simple example gives you some idea of the power behind T4 templates.

What Can T4 Templates Do For Me?

By combining literal text, imperative code, and processing directives, you can transform data in your environment into buildable artifacts for your project. For example, inside a template you might write some C# or Visual Basic code to call a web service or open an Excel spreadsheet. You can use the information you retrieve from those data sources to generate code for business rules, data validation logic, or data transfer objects. The generated code is available when you compile your application.

As an example, let’s imagine we want to work with a SQL Server database. Instead of allowing our application code to use low-level ADO.NET abstractions from System.Data.SqlClient (like DataTable and SqlDataReader), we want to use custom C# class definitions for each table in a database. These classes will hide the ADO.NET details needed to access the table. We can create those classes by hand, or we can use a T4 template to generate the class definitions directly from the database schema.

<#@ template language="C#4.0" #>
<#@ assembly name="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>

<# 
	foreach(var name in GetTableNames())
	{
#>
		public class <#= name #>
		{
		
		}
		
<#  
	} 
#>
<#+
IEnumerable<string> GetTableNames() 
{
	var connectionString = 
                    @"Data Source=.;Initial Catalog=movies;Integrated Security=True";

	var commandText = "select table_name as TableName 
                         from  INFORMATION_SCHEMA.Tables";
	        
	using(var connection = new SqlConnection(connectionString))		
	{
		connection.Open();
		using(var command = new SqlCommand(commandText, connection))
		using(var reader = command.ExecuteReader())
		{
			while (reader.Read())
			{												
				yield return reader["TableName"] as string;
			}	
		}
	}
}

#>

There are a number of new constructs in this template, and some of those constructs we will cover in more detail in the next section. At this point, it’s important to understand that we have the capability to reference .NET assemblies from a template. We can use the types inside those assemblies to perform useful work. In this template, we are using the System.Data assembly and the SqlClient API to retrieve all the table names inside a specific database. We then take the table names and generate a class for each table. The name of each class is the same as the table name – you’ll see this happen in the following section of the template.

<# 
	foreach(var name in GetTableNames())
	{
#>
		public class <#= name #>
		{
		
		}
		
<#  
	} 
#>

Not only do we have access to external assemblies from inside a template, but we also have access to all the features of the C# language (or the Visual Basic language, if you create your template using Visual Basic). In the above section, we are using the foreach control flow statement to loop through the available table names. If we have two tables in the database named movies and reviews, the output of the template will look like the following:

public class movies
{

}

public class reviews
{

}

This meager template is just the beginning of what we’ll need for full featured data access. However, we can already see an advantage over hand crafted code. If we change the name of a table in a database, we don’t have to find and change the name of the corresponding C# class. Instead, we can re-execute the template and regenerate the class definitions. You can force a template transformation by right clicking on a template and selecting “Run Custom Tool” from the context menu.  

After we regenerate code we might need to change the code in our application that uses the old class definition, but the compiler will help us locate these cases. It’s easier to find breaking changes when we generate strongly-typed code for data access. Compare this approach to using DataTables and DataReaders and specifying names using string literals. The compiler is no help in trying to track down breaking changes.

At this point, we could continue working on the template to generate properties for each column in a table, and perform aesthetic work like uppercasing the first letter of each table name (since C# class definitions should begin with a capital letter). However, with the ADO.NET Entity Framework we do not need to operate at this low level, yet we can still use T4 Templates to have complete control over the code we’ll use for data access.

Before we can take a closer look using T4 Templates together with the Entity Framework, let’s drill into specific capabilities of T4 Templates.

Working with T4 Templates

Every developer should know a few basics before working with T4. This includes how to add assembly references, and use control blocks and directives. We’ll start by looking at template directives.

Directives

Directives provide instructions and information to the transformation engine. We used two simple directives in the simple template we wrote earlier.

<#@ template language="C#" #>
<#@ output extension=".txt" #>

The first directive, the template directive, tells the engine what language it should expect to find in the template. You can specify the values C# or VB. We’ll use the C# language in our samples, and this is also the default value if left unspecified.

The output directive gives the processor a file extension for the generated file. A text template generally outputs a single file named the same as the template, but with the extension specified in the output directive. Later, we’ll see templates generating multiple output files.

Additional directives you’ll frequently see are the assembly and import directives.

<#@ assembly name="System.Data" #>
<#@ import namespace="System.Data.SqlClient" #>

The assembly directive references an assembly. Just like a project reference, the public types inside the assembly become available to use from inside the template. Note that the template processor needs to find an assembly in order to use the assembly. For assemblies installed in the global assembly cache, like the System.Data assembly, assembly resolution will not give you any problems. For assemblies not installed in the GAC, you’ll need to provide an absolute path.

Once you’ve referenced an assembly you’ll probably want to use the import directive. The import directive is just like a using statement in C# - the directive brings a namespace into scope so you do not need to use fully qualified type names.

Finally, the include directive allows you to include the contents of another file into a template.

<#@ include file="EF.Utility.CS.ttinclude"#>

The include directive is useful if you want to create reusable content or template code to include into other templates. The file parameter in this directive can specify a relative or absolute path. The template processor will also search the directories listed in the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\TextTemplating\IncludeFolders.

Control Blocks

After directives, there are two types of content you’ll find in a template. The first is the literal text the template will output directly. The second type of content is code inside of control blocks. There are three types of control blocks in T4. The first type is the expression control block, which we delimit with <#= and #> tokens.

This content was generated from a template
in the year <#= DateTime.Now.Year #>

An expression control block is required to produce a value. The template engine will convert the value to a string and write the value into the output where the expression block appears. Note you do not end the expression with a semi-colon.

Standard control blocks are not required to produce a value, and you delimit them with <# and #>.

<#
	var sum = 0;
	for(var i = 0; i < 10; i++)
	{
		sum += i;				
	}
#>

You are free to write multiple lines of code inside a standard control block, and you use types from any referenced assembly. You can query databases, read files, and call web services. But, what do you do with a reusable piece of code? Can you create a method to call from other areas of the template?

This does not compile:

<#	
	int SumNumbers(params int[] numbers)
	{
		return numbers.Sum();
	}
#>

Because of the way text templates compile, the above approach will not work. When the template processor parses the template, it builds a class derived from the TextTransformation class in the Microsoft.VisualStudio.TextTemplating namespace. Once the engine finishes parsing the template it instantiates this class and invokes a TransformText method. The processor builds the TransformText method by taking all the code inside of standard control blocks and placing it inside the method. Since it is illegal in C# to have a named method inside of a method, we’ll create an error condition with the above code.

However, a third type of control block does allow you to create reusable methods. The class feature control block uses <#+ and #> delimiters. The following code will work because the SumNumbers method exists inside a class feature block.

<#@ template language="C#" #>
<#@ output extension=".txt" #>
<#@ assembly name="System.Core.dll" #>
<#@ import namespace="System.Linq" #>

Results:
<#= SumNumbers(1,2,3) #>
<#= SumNumbers(4,5,6,7) #>

<#+	
	int SumNumbers(params int[] numbers)
	{
		return numbers.Sum();
	}
#>

The processing engine takes code inside of a class feature block and adds the code into the class definition it creates to represent the template. This means you can create methods, properties, and fields to reference in other parts of the template. The above template will sample will produce (approximately) the following code:

public partial class SimpleTemplate : TextTransformation
{
    public virtual string TransformText()
    {
        GenerationEnvironment = null;
        Write("\r\nResults:\r\n");
        Write(SumNumbers(1,2,3).ToString());
        Write("\r\n");                        
        Write(SumNumbers(4,5,6,7).ToString());
        this.Write("\r\n\r\n");
        return GenerationEnvironment.ToString();
    }            

    int SumNumbers(params int[] numbers)
    {
        return numbers.Sum();
    }
}

It’s the above class definition that the template processor creates and instantiates. The processor invokes the TransformText method and writes the result into the output file. Notice the method named Write and the property named GenerationEnvironment (it’s of type StringBuilder). The template class inherits these members from the base TextTransformation class, which includes a number of helpful utility methods and properties you can use inside a template. For example, we could have written the above template like the following.

<# 
	Write(SumNumbers(1,2,3).ToString());
	Write(SumNumbers(4,5,6,7).ToString());
#>

<#+	
	int SumNumbers(params int[] numbers)
	{
		return numbers.Sum();
	}
#>

Editing and Debugging Tips

Since T4 templates are text files you can edit them with any text editor, including Visual Studio. However, there are some tools to improve the editing experience. You can find and install these tools from the Visual Studio Gallery.  The gallery is available as a web site (http://visualstudiogallery.msdn.microsoft.com/), or through the Visual Studio extension manager (go to the Tools menu, and select Extension Manager).

In the following screen shot we’ve gone to the Visual Studio Extension Manager and searched the online gallery for “t4 editor”. The results include T4 specific editors from Tangible ( http://www.tangible-engineering.com/) and Clarius Consulting ( http://visualstudiogallery.msdn.microsoft.com/40a887aa-f3be-40ec-a85d-37044b239591/). These editors include various features, including support for Intellisense and syntax coloring.

T4 Editors

Once you’ve finished editing, something might go wrong. If the processor fails to parse the template, you’ll receive error messages in the Error List window. For example, an extraneous <# delimiter will give you the following error messages.

Viewing template errors

You might also run into the scenario where the template processor parses the template but produces illegal C# code because of problem in the template. This scenario will also list errors in the Error List window. An example would be the template we demonstrated with a method defined inside a standard control block instead of inside a class feature block.

Finally, you might run into problems with the execution of the code inside the template. For example, you might see a null reference exception or incorrect output in the generated file because of a bug or miscalculation in your code. In these cases, it can be helpful to step through the template code with a debugger.

First, make sure you put the template into debug mode.

<#@ template language="C#" debug="true" hostspecific="true"#>

Then you can launch the debugger during execution by placing the following line of code in your template.

<# 
    System.Diagnostics.Debugger.Launch(); 
    System.Diagnostics.Debugger.Break();
#>

You can leave the debugger attached and running as you modify and tweak T4 templates. The debugger will continue to break in the template code whenever the template processor executes.

Now that we’ve covered the basics of T4 Template authoring, we can turn our attention to using T4 with the Entity Framework.

The Entity Framework and T4 Templates

At its core, the ADO.NET Entity Framework relies on an Entity Data Model. An EDM provides all the metadata the framework needs to translate LINQ queries into SQL commands and materialize objects from query results. This metadata includes a storage model (which describes a database schema), a conceptual model (which describes entities used in the application), and the mapping between the storage and conceptual models. One approach to creating an EDM is to right-click on a project, select Add New Item, and select the item template named ADO.NET Entity Data Model.

Adding a new ADO.NET Entity Data Model

Adding this item template to a project will create an XML file with an .edmx extension. The XML contents of the .edmx fully describe the conceptual and storage models, as well as the mapping between the two models. The Entity Designer also stores layout information in the .edmx file related to the graphical display of the models on the design surface in Visual Studio. When adding a new EDM item, you can choose to start with an empty model, or generate a model by selecting tables, views, and stored procedures in an existing database.

Generate from database

Regardless of how the EDM comes into existence, a developer can use the Entity Designer to construct a conceptual model of their domain. The conceptual model includes definitions for entities, entity properties, and the relationships between entities. For example, in building a conceptual model of an application to work with movie reviews, you might define Movie and Review entities and include a one to many relationship between the two entities.

Defining the entities

The Entity Designer saves this conceptual model into the .edmx file using an XML derivative known as conceptual schema definition language (CSDL). While tools like the Entity Designer can readily consume CDSL, the developer who wants to work with the conceptual model inside an application needs CLR type definitions – not XML. In this example, we’d expect to work with a class named Movie and a class named Review.

Fortunately, the Entity Designer includes tools to generate code from an EDM. The default code generator is the EntityModelCodeGenerator, and it can transform CSDL into C# or Visual Basic code (creating the object layer, in Entity Framework parlance).  You’ll see this default generator as the custom tool for an .edmx file by default. Whenever you save an .edmx file, the generator will execute and generate the object layer into a .cs or .vb file behind the .edmx file. This is similar to how T4 templates work, but we are not using templates yet.

EntityModelCodeGenerator

If we open the generated Movies.Designer.cs file, we’ll find the following class definition for a Movie (some code omitted for brevity).

[EdmEntityTypeAttribute(NamespaceName="MovieReviewsModel", Name="Movie")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Movie : EntityObject
{
    [EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
    [DataMemberAttribute()]
    public int ID
    {
        get
        {
            return _ID;
        }
        set
        {
            if (_ID != value)
            {
                OnIDChanging(value);
                ReportPropertyChanging("ID");
                _ID = StructuralObject.SetValidValue(value);
                ReportPropertyChanged("ID");
                OnIDChanged();
            }
        }
    }
    ...
}

This is where the Entity Framework faces a dilemma. Different developers apply different constraints and requirements on the entity objects they use. Some developers need entities to derive from a common base class in their application domain. Other developers need entities supporting serialization, change tracking, and change notification. Still other developers demand support for POCOs (plain old CLR objects) – persistence ignorant classes with no ties to any 3rd party framework infrastructure.

Instead of trying to anticipate and fulfill every possible scenario and requirement, the Entity Framework team decided to use T4 templates as an extensibility mechanism. T4 templates allow developers to customize or completely replace the code generation strategy.

Existing T4 Templates for the Entity Framework

In addition to using the EntityModelCodeGenreator, the Entity Framework provides T4 templates for generating the object layer. There are two templates provided with Visual Studio 2010, and additional templates are available for download. To use one of these templates, right-click on the design surface of an .edmx file and select the “Add Code Generation Item” command.

Add Code Generation Item

Selecting the command will launch a dialog box allowing you to select one of the installed code-generation items, or to search for new items online (a topic we’ll revisit later). The two templates installed with Visual Studio 2010 include the “ADO.NET EntityObject Generator”, and the “ADO.NET Self-Tracking Entity Generator”. We’ll look at the EntityObject Generator first.

ADO.NET EntityObject Generator

The EntityObject Generator and Code Generation Strategies

The EntityObject Generator is a T4 template that generates the same default code as the EntityModelCodeGenerator. However, the EntityObject Generator comes in the form of an editable T4 template. The template will become a part of your project, and you can open the template to make modifications. The generated object layer will reflect these modifications. Let’s see how the process works.

In the Add New Item dialog, you can enter a name for the EntityObject Generator. Like all T4 templates, the new item will have a .tt extension. If you look in the Solution Explorer window after you enter a name and click the Add button, you’ll find the .tt file added to the project. The custom tool for the .tt file will be the same TextTemplatingFileGenerator we saw earlier with our simple template. Just as with the simple template, the generator will transform this template into a code file. In the following screen shot, we’ve named the new item Movies.tt.

Movies.tt

The file containing the template output is Movies.cs. As we mentioned earlier, this file will contain the same code we would see generated by the EntityModelCodeGenerator. Before we look at the template creating this code, let’s look at what is different about our .edmx file.

If you examine the properties of the conceptual model you’ll see the Code Generation Strategy value is set to “None”. You can examine the property by double-clicking the .edmx file to open the file in the designer, then right-clicking in the white space of the designer and selecting Properties. A value of “None” means the EntityModelCodeGenerator will no longer create an object layer in the Movies.Designer.cs file. The file still exists, but if you open the file you’ll only find a comment telling you that default code generation is disabled. If you want to return to using the default code generation strategy, change the value to “Default”.

Using the default code generation strategy

It’s important to understand that even though Code Generation Strategy is set to “None” we are still generating code, and the EDM is still the authoritative source of the conceptual model. Looking inside the EntityObject generator template, you’ll find the following lines of code near the top of the template.

UserSettings userSettings =
        new UserSettings
        {
            SourceCsdlPath = @"Movies.edmx",
            ReferenceCsdlPaths = new string[] {},
            FullyQualifySystemTypes = true,
            CreateContextAddToMethods = true,
            CamelCaseFields = false,
        };

Notice the SourceCsdlPath property of the UserSettings. The property holds a relative path to the .edmx file the template will use to generate code. Thus, the generated code will continue to reflect changes made in the Entity Designer.

The ADO.NET Self Tracking Entity Generator and Multiple Output Files

The second built-in template you can use to generate the object layer is the ADO.NET Self Tracking Entity Generator. The entities generated from this template are responsible for recording any state changes they experience. You can disconnect these entities from their object context, serialize and pass them into different tiers of an application, then reattach them at a later point to persist any recorded modifications.

Unlike the EntityObject generator, the self-tracking entity generator adds two templates to a project. The first template generates the ObjectContext derived class you need to retrieve and save entities (this template ends with .Context.tt). The second template generates the entities themselves and an ObjectChangeTracker helper class. Unlike the templates we’ve seen so far, each of these templates generate multiple output files.

Generating multiple files from a template

In the above screen shot, you can see a .cs file for each entity (Movie.cs and Review.cs). T4 templates do not directly support the generation of multiple files, so the template relies on a helper class named EntityFrameworkTemplateFileManager. The definition for this class is in EF.Utility.CS.ttinclude (EF.Utility.VB.include for VB templates), and all the EF templates we’ll look at include this file (it lives under the Visual Studio installation directory in Common7\IDE\Extensions\Microsoft\Entity Framework Tools\Templates\Includes).

EntityFrameworkTemplateFileManager

The EntityFrameworkTemplateFileManager is a class you can use in your own custom templates once you understand the simple API. The following template demonstrates the basics.

<#@ template debug="true" hostspecific="true" language="C#" #>
<#@ output extension=".txt" #>
<#@ include file="EF.Utility.CS.ttinclude"#>

<#
  var fileManager = EntityFrameworkTemplateFileManager.Create(this);
  fileManager.StartHeader();
#>
-- This line is a common header to use in every generated file. 
<# 
  for(var i = 0; i < 3; i++) 
  {
    fileManager.StartNewFile("file_" + i.ToString() + ".txt");
	#>
		Here is some content for file # <#= i.ToString() #>
	<#
  }
  fileManager.Process();
#>

The file manager will replicate any output you emit from a template after a call to StartHeader or StartFooter into every file you create from a template. Header content will go at the start of the output file, while footer content will go to the bottom. Creating a new file is as easy as invoking StartNewFile and generating some output. The file manager is smart enough to keep track of where the intended output should go – header, footer, or directly to one (of possibly many) files.

Finally, invoke the Process method when you are ready for the file manager to write all the separate files. With the above template, we’ll create 4 files (one output file for the template itself, and three files we’ve created with the StartNewFile method).

Files generated by StartNewFile

The contents of file_0.txt will look like the following.

-- This line is a common header to use in every generated file. 
		Here is some content for file # 0

Host Specific Templates

Note there is an extremely important setting in the template directive of the last sample.

<#@ template debug="true" hostspecific="true" language="C#" #>

The EntityFrameworkTemplateFileManager (and the EF templates in general) require the hostspecific=”true” setting in the template directive (the default value for this attribute is false). Setting this value to true allows code inside the template to access a Host property and communicate with the both the template transformation engine and Visual Studio. You can use the template host to resolve path names, and retrieve other parameter values, like the name of the executing template file.

Additional Templates and the POCO Entity Generator and

Shortly after the release of EF 4.0 and Visual Studio 2010, developers from inside and outside of Microsoft began to provide additional T4 templates for use with the Entity Framework. You can install these additional templates from the Visual Studio Gallery.

In the following screenshot, we’ve gone to the Visual Studio Extension Manager, selected the Online Gallery, and searched for the term “entity”. The top result in this search is the “ADO.NET C# POCO Entity Generator”. POCO stands for “plain old CLR object” and implies an object with no ties to data access APIs or 3rd party infrastructure. The EF team created this template to provide support for generating simple POCO class definitions from an EDM. Clicking Download will automatically download and install the template.

Installing the ADO.NET C# POCO Entity Generator

Once the extension is installed, you’ll be able to use the POCO template as easily as the built-in templates. Right-click on the Entity Designer to add a new code generation item, and you’ll be able to select the template from the list of available templates.

Using the ADO.NET C# POCO Entity Generator

Like the self-tracking entity generator, the POCO generator will add multiple templates to a project, and use the EntityFrameworkTemplateFileManager to emit multiple files from a single template.

Output of the ADO.NET C# POCO Entity Generator

All three of the code generators have a similar internal structure and use the same helper classes. We’ll learn about these pieces in the next section when we customize a template.

Customizing Templates

When the available code generation templates don’t suit your needs, you have the choice of changing the existing templates or writing your own template from scratch. Obviously, if you are mostly happy with the output of a template, but you need some small changes, then modifying an existing template is the best approach. However, even if you want to start a template from scratch, there is reusable code provided by the EF templates to make the job easier.

Entity Framework Metadata

The EDM contains a vast amount of metadata you’ll want to utilize in a custom template. The loading and parsing of the .edmx file containing this metadata is something the helper classes can manage for you. All three templates begin with essentially the following code.

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#>
<#@ output extension=".cs"#>
<#

CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);

string inputFile = @"..\Movies.edmx";
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = code.VsNamespaceSuggestion();

EntityFrameworkTemplateFileManager fileManager =
          EntityFrameworkTemplateFileManager.Create(this);
#>

The second line is the include directive to bring in  EF.Utility.CS.ttinclude. As we mentioned earlier, this file lives in a well-known directory where the T4 engine will find it, and includes the definition of several utility classes - including the MetadataLoader, MetadataTools, CodeRegion, and CodeGenerationTools.

The MetadataLoader is responsible for parsing an .edmx file into an EdmItemCollection. This collection class lives in the System.Data.Metadata.Edm namespace of the System.Data.Entity assembly (so it is part of the Entity Framework and .NET, and not just a helper class defined in a template). An EdmItemCollection will hold objects representing pieces of the conceptual model, like EntityType objects. The MetadataLoader can also load metadata from the StorageItemCollection and StorageMappingItemCollection. Not all templates will need this additional storage and mapping metadata, but you will find it used in the ADO.NET Self Tracking Entity Generator template.

The POCO generator uses the EdmItemCollection in the following code to begin creating entity class definitions.

// Emit Entity Types
foreach (EntityType entity in ItemCollection.GetItems<EntityType>()
                                            .OrderBy(e => e.Name))
{
    fileManager.StartNewFile(entity.Name + ".cs");

    ...

You can see the EntityFrameworkTemplateFileManager again in the above code. The file manager allows the template to create one file per entity. The EntityType object the code uses ultimately inherits from an EdmType class, and exposes a number of useful properties to reveal information about an entity, like the entity’s name, base type, properties, and navigational properties.

EntityType hierarchy

A template can use an EntityType it retrieves from the EdmItemCollection to create properties for entity objects. The following foreach statement in the POCO template demonstrates this capability (it’s looping through the primitive properties explicitly declared on this type only).

foreach (EdmProperty edmProperty in 
         entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType &&
                                      p.DeclaringType == entity))

Code Generation Helpers

The included EF utilities also define CodeRegion and CodeGenerationTools to ease the pain of code formatting. For example, the CodeRegion class includes Begin and End methods to emit #region and #endregion into the generated C# code and omitting the region if the template does not generate code inside the region..  The CodeGenerationTools class includes overloaded version of an Escape method to transform string and EDM objects into strings you can use as legal C# identifiers.

CodeGenerationTools

As an example, the POCO templates uses the CodeGenerationTools when writing out the class name of an entity.

partial class <#=code.Escape(entity)#>
              <#=code.StringBefore(" : ", code.Escape(entity.BaseType))#>

Modifying the EntityObject Generator

Let’s customize the ADO.NET EntityObject Generator to include attributes from the System.ComponentModel.DataAnnotations namespace. Several validation frameworks recognize attributes in this namespace and use them to perform validation checks on an object. For example, the default model binder in ASP.NET MVC will look for attributes like [Required] and [StringLength] to ensure a given object is in a valid state.

By default, the EF templates do not add any annotations to an object, yet there is information available in the EDM that will let us apply these attributes. Every EdmProperty object inherits a TypeUsage property, and a TypeUsage object includes a Facets collection. Facets contain additional information about a property, like it’s nullability and the maximum length (for string types).

TypeUsage and Facets

The EntityObject Generator is a large template – currently over 1,200 lines of code, not counting the helper classes we reviewed earlier. However, if all you need to do is to make small changes to the default generated code, then modifying this template is easier than starting from scratch.

First, we can add our own helper methods in the template to retrieve the MaxLength and Nullable facets of a TypeUsage object. You’ll need to place these methods in the class feature block at the bottom of the template (in the current version of the EntityObject Generator template, the class feature blocks starts around line 723).

private bool IsNullable(TypeUsage usage)
{
	return (bool)usage.Facets.First(facet => facet.Name == "Nullable").Value;
}

private bool HasMaxLength(TypeUsage usage)
{
	return usage.Facets.Any(facet => facet.Name == "MaxLength");	
}

private int MaxLength(TypeUsage usage)
{
	return (int)usage.Facets.First(facet => facet.Name == "MaxLength").Value;	
}

To place the annotations into the generated code, we’ll need to either fully qualify the attribute type names or add a using statement for System.ComponentModel.DataAnnotations. We’ll go with the using statement approach. The using statements the template generates are included as literal text around line 60. We’ll add the annotations namespace to the end of the list.

using System;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Data.EntityClient;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.ComponentModel.DataAnnotations;

Finally, we need to add the attributes themselves. Around line 336 of the template, you’ll find the foreach loop to process primitive properties.

foreach (EdmProperty property in 
         complex.Properties.Where(p => p.DeclaringType == complex &&
                                  p.TypeUsage.EdmType is PrimitiveType))
{
    VerifyGetterAndSetterAccessibilityCompatability(property);
    WritePrimitiveTypeProperty(property, code);
}

As can see, the code delegates responsibility for writing the property to a method named WritePrimitiveTypeProperty. You’ll find this method defined around line 547. Towards the top of the method you’ll see the code output the DataMemberAttribute. We can add our attributes just after the DataMemberAttribute.

<#+ if (IsNullable(primitiveProperty.TypeUsage)) { #>
	[Required]
<#+ } if(HasMaxLength(primitiveProperty.TypeUsage)) { #>
	[StringLength(<#=MaxLength(primitiveProperty.TypeUsage) #>)]	   	
<#+ } #>

Note the WritePrimitiveTypeProperty method is in a class feature block, so we are using class feature blocks in the above code. When the template runs, it can generate the following code.

[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=false)]
[DataMemberAttribute()]
[Required]
[StringLength(64)]	   	

public global::System.String Title
{
    get
    {
        return _Title;
    }
    set
    {
        OnTitleChanging(value);
        ReportPropertyChanging("Title");
        _Title = StructuralObject.SetValidValue(value, false);
        ReportPropertyChanged("Title");
        OnTitleChanged();
    }
}

Conclusion

In this paper we’ve looked at the capabilities of T4 Templates and demonstrated how the Entity Framework leverages templates for code generation. The EDM is still the centerpiece of the code generation strategy, and inside the templates we’ve pointed to some utility classes, like the MetadataLoader, that make working with the EDM easier. Even though the EDM metadata drives all the code generation by default, you can use the power of templates to pull in custom metadata from any data source and augment the generated code with custom members and attributes. Templates allow the best of both worlds – the code generation of strongly typed classes for an object layer and also the flexibility of customization and total control.