Skip to main content

A bit about .tt templates used in Entity Framework and not only

Most developers that have used Entity Framework will surely have noticed some special files in the project that end in ".tt". These files serve as blueprints for the code that is generated from the Entity Framework mappings which are stored in an xml file ending in ".edmx".

A ".tt" template is similar to the ".cshtml" files used in Asp .Net MVC but instead of rendering html content it renders C# code. By editing these files we can customize how the generated code will look and behave.

For example the partial ".tt" template bellow for each column in a table in the database it generates a property that implements the INotifyPropertyChanged interface to notify subscribers that the object has changed:

public string Property(EdmProperty edmProperty)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1} {2} {{ {3}get {{ return _{5}; }} {4}set {{ _{5} = value; OnPropertyChanged(); }} }}",
Accessibility.ForProperty(edmProperty),
_typeMapper.GetTypeName(edmProperty.TypeUsage),
_code.Escape(edmProperty),
_code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
_code.SpaceAfter(Accessibility.ForSetter(edmProperty)),
_code.Escape(edmProperty).ToLower());
}
view raw template.cs hosted with ❤ by GitHub
This is applied for each column in every table. Using this code we can bind our objects directly to a Windows Presentation Foundation interface after fetching them from the database.

We can also generated backing fields for that property using the following template bellow:

public string BackingField(EdmProperty edmProperty)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1} _{2};",
"private",
_typeMapper.GetTypeName(edmProperty.TypeUsage),
_code.Escape(edmProperty).ToLower());
}
view raw template2.cs hosted with ❤ by GitHub


The generated properties along with the generated fields and class will look like this:

public partial class Calibru : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
private int _id;
public int Id { get { return _id; } set { _id = value; OnPropertyChanged(); } }
private int _reperid;
public int ReperId { get { return _reperid; } set { _reperid = value; OnPropertyChanged(); } }
private string _nume;
public string Nume { get { return _nume; } set { _nume = value; OnPropertyChanged(); } }
private string _valoare;
public string Valoare { get { return _valoare; } set { _valoare = value; OnPropertyChanged(); } }
public virtual Reper Repere { get; set; }
}
view raw template3.cs hosted with ❤ by GitHub


You can mix C# code which will get executed in a template with declarative content that will appear as it is in the generated C# code:

<#=codeStringGenerator.UsingDirectives(inHeader: false)#>
<#=codeStringGenerator.EntityClassOpening(entity)#>
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
<#
view raw template5.tt hosted with ❤ by GitHub


The C# code that is executed when the template is evaluated has to be encompassed in special "<#" and "#>" markings. This C# code is separate from the generated C# code and is actually used to output C# code.

If the code returns a simple string value we can use "<#=" to include the string value directly in the generated C# code. Other text that is not encompassed in the special markings mentioned above will appear as it is.

Loops can be used to generate code multiple times. You can have declarative code inside an actual foreach loop in C# code. The declarative code will get multiplied for each element. Bellow you can see an example but it looks a bit confusing at first:

public <#=code.Escape(complex)#>()
{
<#
foreach (var edmProperty in propertiesWithDefaultValues)
{
#>
this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
<#
}
foreach (var complexProperty in complexProperties)
{
#>
this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
}
#>
}
view raw template6.tt hosted with ❤ by GitHub


Additionally you can generate multiple files for each table. You can for example generate an abstract data access layer with interfaces that include CRUD methods. So for each table you will have some kind of repository interface like "ITableRepository". And then for these interfaces you can generate actual classes which implement them and return data from the database.

There are probably other ways you can use these templates. Also a downside is that Visual Studio by default does not include syntax highlighting support and actually proper IDE support for editing them.


Comments

Popular posts from this blog

Some software development common sense ideas

 I haven't really written here in a long time so it's time to write some new things. These are just some random common sense things that seemed to short to write about individually but seem really interesting and useful to me or other people 1. There is nothing fixed in software development, all things vary by circumstances and time Remember the documentation that didn't seem that important when you started the project, well after a couple of years one the application has grown and become really complicated, no one actually knows everything about the application anymore. So now you really need that documentation. What happens if you suddenly need much more people to develop the application because of some explosive growth? Without documentation, new developers will just look at the application like they look at a painting. This actually happened to me. Maybe in the beginning of a project, a technology really helped you a lot but as the project grew, it started making things...

Some things which are often blindly applied and followed by developers which are not always good

This is probably one of the most controversial things that I have written so far but I am just tired of hearing about these things and discussing these things. Other developers that I know share part of my feelings. I would rather hear more about how people built things, overcame challenges or what new interesting ideas and concepts they implemented. Those things are really interesting and innovative, not hearing about the same theoretical things over and over again. I can just read and learn those things from 100 sources on the internet. Firstly, one of the most discussed and promoted things is agile/scrum development. I think I have been through 5-8 workshops about agile development methodology. And each time, some things differed. There is no 100% standard approach to this. Everyone uses their own version of this development methodology and seem to argue a lot that their approach is right and everyone else is doing it wrong. You go to an interview, this will be one of the first 10 t...

Some things about doing presentations that I learned recently

Lately I had to do more presentations ranging from technical ones about various technologies to other presentation about projects that I work on or even tools that I made for developers and testers. I didn't learn a big list of things from them but rather a couple of really important things to keep in mind when doing a presentation. To begin with, as a presenter your purpose is to make people understand what you are explaining first and foremost. I have seen all too many experienced developers trying to impress the audience when presenting something. They use a lot of pompous language, terms and jargon to make things seem more complicated than they really are. This is just to feed their own ego, to send a subliminal message to the crowd over the lines of: "Look at me how good I am, I managed to understand and apply these things which sound really complicated when I tell them". Imagine if they used a more simple language and a language which is less scary and intimid...