I love the new Entity Framework 4 T4 templates for generating POCO’s and Self Tracking Entities. However the generated code ends up in a single assembly, mixing database independent POCO’s and STE’s with Entity Framework specific code. I like my entities to be in another project. How can we do this? This blog post is a walk-through on how to do this.
For this to work we need at least two library projects, one for the entities, and one for the data access layer.
In your data access layer project start by adding your Entity Framework (EF) model, either using database first or model first. In this walk-through I’ll be using database first, and using Northwind (gasp) as the database.
Add a new ADO.NET Entity Data Model to the DAL project, calling it NorthwindModel.edmx:
In the wizard choose “Generate from database”:
Follow through with the wizard, at the end selecting Categories and Products:
Update your model as you see fit…
The code being generated is the old EF3 kind of code, with classes deriving from EntityObject. I don’t want to use these classes as they couple my entities too much to EF. So instead I want to use Self Tracking Entities (of POCO’s). Next step is to right-click your model’s background and select Add Code Generation Item…
In this case you will be asked what code generation template you’d like to use. These template are actually T4 templates you can customize.
Choose the template of your liking, I’ll choose the ADO.NET Self-Tracking Entity generator using NorthwindModel.tt as the name. This will generate entities who will easily travel over borders using WCF. POCO’s lack the DataContract and DataMember support, but if you like, you can always add these to the T4 template yourself. More on this in a later post.
You should now end up with three files in your project:
The first contains EF specific code, so you should leave that one here. The second is the model, again EF specific. The third file, however, contains your entities and can be used without EF, so I’d like to move that to my entities project.
Unfortunately you cannot simply move the file over to the other project, because inside the NorthwindModel.tt T4 file there is a direct reference to the model:
string inputFile = @"NorthwindModel.edmx";
So we’ll need to use another technique. Right-click on your entities project and choose Add Existing Item…
Browse to your DAL project and search for the NorthwindModel.tt file (you’ll need to change the file filter in the dialog). Now you want to click on the little arrow on the add button and select the Add As Link option. This option will leave the file in its original location where the model’s file reference can be found.
However, the generated code will now be part of your entities library. Before you compile the entities project you’ll need to add a reference to System.Runtime.Serialization because the STE use the WCF’s DataContract attributes. Also, make sure the T4 code generation happens by right-clicking the NorthwindModel.tt file and selecting Run Custom Tool:
Now go back to the DAL project. We need to remove the code generation for the model in this project (since the code is now in the entities project). Right-click the NorthwindModel.tt file and select Exclude from Project:
The final problem will happen when you try to compile the DAL project. The compiler will complain it cannot find a range of classes, such as Category and IObjectWithChangeTracker. This is because the generated NorthwindModel.Context.tt code lives in another namespace as the NorthwindModel.tt generated files (which include Category and IObjectWithChangeTracker). So how can we solve this. One way is to tell the code generator to use the same namespace and you can do that by selecting the NorthwindModel.Context.tt file and changing the Custom Tool Namespace property to the namespace of your entities project:
Or you could add a using statement to the NorthwindModel.Context.tt file so it generates a using ‘EntityNamespace"’ statement into the generated code (left as an exercise for you, the reader). I like the first solution, since the generated code is only used inside the implementation of the DAL, so using the “wrong” namespace should cause much of a problem. Since your code, which uses the entities will need a using statement anyway, you won’t see any difference in your code.