D3: Using T4 to Generate Entity and Context Classes
Sorry for the DPMud hiatus. Here’s another installment for those interested in the process. I’m still trying to get a public source repository up. Until that’s functional I’m not going to do a lot of development because I want to share the process with you. In the meantime I’m still laying groundwork where I can, and one aspect of that is using T4 to generate classes for the entities and for the data access layer.
Side Note: We’ve been trying hard to refer to EF versions using the corresponding .net version rather than “v1” and “v2” since talking in terms of .net versions makes it clear when and how the corresponding versions ship. So don’t be surprised when I refer to EF4 or EF3.5.
The idea behind using T4 for code generation is that I’d like to create the DPMud model using the EF Designer and then generate both the classes and the database from the model (database generation has been discussed previously on the EF Design blog). There are two key architectural requirements for these classes that we generate:
- The entities should be completely persistence ignorant. That is, they should live in an assembly which doesn’t have any dependency on Entity Framework or ADO.Net DLLs. One concrete reason for this is that I want to reuse the entity classes in Silverlight. Happily, EF4 adds extensive support for POCO entity classes.
- The DAL should be designed in a way that supports easy introduction of a fake implementation. That is, it should be a “seam” in the terminology of design for testability. Another feature of EF4 which supports this is the introduction of a new interface, IObjectSet<T> which is implemented by the ObjectSet<T> class which provides both a starting point for queries and a place to add and remove entities of that type.
So I created a couple T4 templates. They share some infrastructure for helping to read EF metadata, escaping identifiers, generating multiple files, one per class, etc. We’re working on getting that infrastructure into the core product, so I’ll concentrate on the unique parts of these templates.
The entity template iterates over each entity type in the metadata and generates a partial class with each property marked virtual so that an automatic EF proxy can be generated if necessary. For navigation properties, it generates properties that are simple CLR references or ICollection<T> instances with an implementation that does fixup. The fixup implementation is generated so that it can be included in the entity DLL and not introduce any other requirements to the entity classes.
The context template generates a class which inherits from ObjectContext and has properties that return ObjectSet<T> instances. It also generates an interface for the seam with IObjectSet<T> properties and a fake context implementation which has fake object set instances which have a very simple wrapper around hashset<T>.
This way I can put the entities into one DLL and the context, interface and fake context into a separate DLL for the DAL.