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.

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.

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.

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.

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.

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
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.

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.

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.

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 3
rd 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.

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.
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.

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”.

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.

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).

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).

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 3
rd 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.

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.

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.

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.

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.

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).

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.
Scott Allen
from msdn