Microsoft Spain has been working very hard in an interesting project since August, 2009. The project consists of a .NET 4.0 n-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.
If you want to know more about this amazing project leaded by César de la Torre, please visit: http://microsoftnlayerapp.codeplex.com/ Also, if you want to view a non-standard diagram (“the big picture”) depicting this reference architecture, you can find it here.
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 the Change 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 edit it with the provided Entity Framework designer:
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 coupled with the Entity Framework infrastructure which 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-end n-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 open both .tt files and edit the inputFile variable to point to your Model.edmx file 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 originally 1671 lines long. It generates two C# files, as shown below: “STE.Context.cs” and “STE.Context.Extensions.cs”
[PLUMBING REUSABLE CODE]
This file always contains 1209 lines of code NO matter how big is your Model.edmx file.
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.
The lines of generated code depend on 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.
[PLUMBING REUSABLE CODE]
This file always contains 417 lines of code NO matter how big is your Model.edmx file.
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-tracking information is populated at 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 Entities OR code 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 accurately interpret the entity graph state and then generate the correct SQL statements to update the DB.
This 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.
“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 Microsoft Spain 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.tt needs to be edited in order to be split into two T4 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…
The .NET 4.0 flavor (EF 4.0 with STE) sample application consists of three T4 templates (red boxes) in the Persistence Layer as depicted below. Notice that the original untouched VS 2010 STE T4 template, STE.Context.tt, has now become: MainModuleUnitOfWork.Context.tt (without being partitioned in 2 independent T4 files).
So far, so good…let’s explain briefly the above three T4 templates:
- MainModuleDataModel.Views.tt: This T4 template is for Views Generation.
- 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”.
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 that WriteApplyChanges(…) 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.
- MainModuleUnitOfWork.Context.tt: As you already know now, this T4 file generates all stuff related to the EF Context (including extensions). The generated context implements the above C# interface.
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.
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 of Infrastructure.Data.Core.
Maybe we can suggest this tiny change to César de la Torre.
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 CORE assembly. 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.
Thanks for your time!