Microsoft Spain has been working very hard in an interesting project since August, 2009. The project consists of a .NET 4.0n-tier sample application(currently evolving to Entity Framework 4.1: “Code First”) and a companion guide in which they map accurately several Microsoft .NET technologies(Entity Framework, ASP.NET MVC, Silverlight, WPF, WCF, Unity, etc.) to a Domain-Oriented .NET reference architecture.

OK! Now, let’s go back to our topic regarding this post’s title. The goal here is to explain as clear as possible the use of the T4 Self-Tracking Entities (STE) templates in the context of the DDD .NET 4.0 sample application by Microsoft Spain. This review is based on theChange Set 62725. (May 31th, 2011).

Out-of-box VS 2010 STE T4 templates

First, let’s review the STE T4 templates without any modifications.

When working with Entity Framework 4.0, it is common to create first a model using a designer.

Within the Solution Explorer your model appears as follows:

You can open and editit with the provided Entity Frameworkdesigner:

Note: It is important to disable the default code generation strategy (EF 1.0) by changing the following model designer property value to None. This prevents you to use prescriptive domain entities which inherit from “EntityObject”.

Inheriting from “EntityObject” makes your architecture coupledwith the Entity Framework infrastructurewhich is NOT desirable in terms of the Domain-oriented mindset.

Finally, you add a T4 template to generate your C# classes representing your domain entities. There are several strategies you can choose from. However, in this case, we are going to choose the “Self-Tracking Entities” T4 template because that is the strategy Microsoft Spain chose in their reference application to support pure .NET end-to-endn-tier scenarios: .NET at the client and server side.

As soon as you have added the STE T4 template, your solution explorer will look like this. Notice that two T4 templates were added to your C# project:

T4 template for the EF context (and Extensions): “STE.Context.tt”

T4 template for your domain entities: “STE.tt”

Now, you just need to openboth.tt files and edit the inputFile variable to point to your Model.edmxfile in order to generate your C# domain classes.

After you are done, your solution explorer may look like this:

Good! But…why is this important to know? Well, by knowing how this works, it is easier for you to understand what Microsoft Spain did with the custom T4 templates.

STE.Context.tt (“EF Context”)

This T4 template generates the EF context C# class and some plumbing C# classes as well; it is originally1671 lines long. It generates two C# files, as shown below: “STE.Context.cs”and “STE.Context.Extensions.cs”

The most important bits about these EF context’s extensions are the oveloaded versions of the ApplyChanges(…) extension method which is public. ApplyChanges() is needed for the EF context to acknowledge the changes made to the entity graph by the client tier.

STE.Context.CSThe lines of generated code dependon the number of domain entities in your model. Notice this class inherits from ObjectContext, so this is what we always refer to as the “context” or “EF context”.

STE.tt (“Domain Entities”)

This second and last T4 template generates your C# domain entities as well as some plumbing C# classes in order to support the change-tracking feature in n-tier scenarios: entities “disconnected/unattached” from EF context. This T4 template is originally 1936 lines of code long.

This file contains a bunch of C# classes and interfaces that support the change-tracking feature in pure .NET-to-.NET n-tier (“disconnected”) scenarios. These classes can be roughly divided in 2 groups:

“Data containers” C# classes which are serializable:dictionaries, mainly. They represent what properties/relationships have been added, modified or deleted at the client side. This change-trackinginformation is populatedat the client-tier and then processed at the server–tier to acknowledge the EF Context the NEW state of the entity. This acknowledgment is done by means of EF Extensions: ApplyChanges(…)

C# classes containing client-tier algorithms that leverage the change-tracking feature. Their main purpose is to populate the “data containers” mentioned above. This C# generated code is very useful and increases your productivity when using .NET client technologies: Silverlight, WPF, WP. Otherwise, if you want to use a non-.NET client(Java, iPhone, Android, etc.) maybe you need to reconsider using Self-Tracking EntitiesORcode yourself these algorithms in their non-.NET platform OR better yet, try the new .NET 4.1 (“code-first”) n-tier sample application by Microsoft Spain in which they shift to Data Transfer Objects(DTOs), which are platform-agnostic objects and optimized to be interoperable.

These groups of classes “tell the EF context” what changed in the entity while modified in the client tier. That way, the EF context can accuratelyinterpret the entitygraphstate and then generate the correct SQLstatements to update the DB.

BankAccount.CSThis is just a sample generated domain entity. Notice it does not depend on any Entity Framework infrastructure class. However, in order to support change-tracking, it needs to implement 2 interfaces. As you can observe, the T4 template also generated some attributes to make them ready to use in a WCF service.

So, what?

“Right!, now I understand the purpose of each original out-of-box STE T4 template and what files they generate and what they are for, so what?”

Yep! With that background now it is easy to reason what MicrosoftSpain really did with the above T4 templates: reusable generated code can be placed in a CORE library in order to be referenced by other assemblies. That way, we avoid code duplication. But wait! That’s not the only modification they did, but I think it is important to understand better the architecture.

STE.tt is split in two T4 templates

The following diagram shows that STE.ttneeds to be edited in order to be split into twoT4 templates:

MainModuleContext.Types.tt: Generates domain-specific code (“your domain entities”). That way, if your application needs let’s say 3 additional modules, you just need to copy this T4 template in its own C# project, point to its specific Model.edmx file and then generate your module-specific entities.(Of course, you need to rename your T4 template to reflect the actual aim of your C# project/module!!!)

ObjectChangeTracker.Types.tt: Generates reusable generated code (“entities plumbing”). Continuing with the above example, your additional 3 modules just need to reference the Domain.Core.Entities assembly (where this T4 file lives) and they are ready to go. You have just get ridden of repeating 3 times the same generated code. (DRY)

In Solution Explorer, these two T4 templates are located as follows. Note that MainModuleContext.Types.cs (reusable code)is useless now because its generated code now lives in another assembly: Domain.CORE.Entities. Particularly, it lives inside ObjectChangeTracker.Types.cs

Why STE.Context.tt T4 template

is NOT split just like STE.tt?

Good question! Indeed, I didn’t realize that until writing this post! More about this in a while…

IMainModuleUnitOfWork.tt: This was created by Microsoft Spain in order to support Unit of Work abstractions. It is really a subset of the next T4 template and it generates a C# interface that inherits from “IQueryableUnitOfWork”. Note: Some annoying things about this T4 template are the hard-coded strings: “IMainModuleUnitOfWork” (LINE 32), using statements (LINE 24) and a bunch of dead code (LINES 130-1323). Regarding the hard-coded strings, it is easy to fix using variables. And regarding the dead code, I think thatWriteApplyChanges(…)T4 function, which generates the “context extensions” (LINES 130-1323), can be deleted safely because that code is generated by the next T4 template. Doing so, makes this template about 100 lines long.

If you are a careful reader, you may have noticed the lack of 159 lines of code from the untouched “STE.Context.tt” to this “MainModuleUnitOfWork.Context.tt file”. Why? As far as I understand it is just to get rid of some non-crucial (“formatting”) generated code.

Note: This T4 template suffers from the same annoying hardcoded strings: LINES 24, 29 and 83. However, this has solution.

OK! So…back to your question…why the original STE.Context.tt T4 template was not split in two T4 templates if we already know that the generated context extensions code is reusable and that it can be hosted in the Infrastructure.Data.Core C# project?

As you may guess, editing T4 templates is not the most exciting task in the world, I think. However, that is possible and in fact, it can be accomplished with just one minor tweak: the context extensions’ StoreReferenceKeyValues(…) method must change its access modifier from internal to public in order to consume it from outside ofInfrastructure.Data.Core.

You have reviewed the purpose of the original T4 templates when selecting the Self-Tracking Entities strategy within the context of a n-tier application. We learnt that STE is a good option when designing a pure .NET-to-NET application because it leverages our productivity. By reviewing the original and untouched STE T4 templates, we acquired a reasonable amount of knowledge to tackle the custom T4 templates that Microsoft Spain created.

You noticed how it is a very good idea to separate reusable code and place it in a COREassembly. Microsoft Spain accomplished that by editing one of the T4 templates: the one that generates the domain entities. The same procedure could also be applied to the context extensions regarding the T4 template that generates EF context stuff, but this was not done. This post encourages this as a suggestion.

Finally, you also noticed some minor annoying things regarding the T4 template that generates the context (MainModuleUnitOfWork.Context.tt) and the other one that support the Unit of Work pattern (IMainModuleUnitOfWork.tt):hard-coded strings and dead code. However, this can be fixed easily. You can download our custom T4 templates (Context.tt & IContext.tt) solving these minor issues from here.