You may already be familiar with the fact that ASP.NET MVC 3 tooling includes a scaffolding option that let’s you point to a domain class and automatically build a Controller, a set of Views and if it does not exist yet, an Entity Framework DbContext class expose that class. The controller CRUD code uses the DbContext to perform it’s operations. Scott’s Guthrie & Hanselman both introduced us to this in blog posts last spring and I’ve certainly demo’d it way too many times.
This is handy but it puts all of the data access code into the controller. In other words, the controller works directly with the DbContext to perform queries & updates (etc).
If you have been paying attention, you may also be aware of the MVCScaffolding NuGet package that adds to these capabilities.
With this installed there are two new templates added to the MVC Add Controller wizard, one which adds a simple repository to the mix.
MVCScaffolding relies on another NuGet package, T4Scaffolding which contains many of the scaffolding templates used by MVCScaffolding.
I was working on the back end of a new app that may or may not have MVC as it’s front end UI. I had created my domain classes and the next step was to create a DbContext to wrap them as well as repositories. I didn’t want to code those by hand. I wanted that MVC tooling to get some of the grunt work out of the way for me. A little reading helped me learn that I could use the T4Scaffolding directly to get the same DbContext & Repository creation without being part of an MVC app (i.e. no controllers or views created).
Here’s how I worked it out.
In my solution where I already had my DomainClasses project, I added a new project, Data Layer.
I then installed Entity Framework via NuGet into this project:
Notice that NuGet automatically picks up the the latest version of EF, 4.3. I could have used the Package Manager Library UI to install EF, but since I had to the rest in the console window, I’m just doing all of these tasks in the console window.
Next, I install T4Scaffolding.
Important Pointers!
- Currently, T4 Scaffolding will install EF 4.1 if you don’t already have EF 4.1 or greater in your project. That’s why I installed EF first, so I can be sure to use the newest version.
- In the package manager console window, I have my default project pointing to DataLayer. I often forget to specify the project and install NuGet packages into the wrong project.
With the package installed, I can now start working towards letting it build out the context & repository for me.
First I need to reference DomainClasses from the DataLayer project
Then I build the solution so that DataLayer can see the DomainClasses for the next step.
Now in the Package Manager Console Window, I’ll use the command to build the repository code. The T4 template that builds the context & repo is called repository. The command is scaffold. I want to run scaffold using the repository template and base the output on my Alias class. I must use Alias’ fully qualified name so that it can be found.
The command is
scaffold repository DomainClasses.Alias
However, I want to specify the name of my context. The default will be DataLayerContext (using the project name). I want it to be TwitterContext.
scaffold repository DomainClasses.Alias -DbContextType:TwitterContext
The result is that a new context & repository class get created in the target project (DataLayer).
There’s some default behavior that is not exactly to my liking and I can use additional parameters as well as modify the T4 template (here’s a post from Steve Sanderson as part of the MVC Scaffolding series that will help with that) but for now I’m happy to just move files around, which I’ll do shortly.
Here’s the context class.
public class TwitterContext : DbContext
{
public DbSet<DomainClasses.Alias> Aliases { get; set; }
}
Now I’ll add another class from my domain model to the mix: Tweet.
Notice that since TwitterContext already existed, we don’t get a second context class, the template alters the existing one:
public class TwitterContext : DbContext
{
public DbSet<DomainClasses.Alias> Aliases { get; set; }
public DbSet<DomainClasses.Tweet> Tweets { get; set; }
}
Finally, I’ll just move things around so they are more to my liking:
I’ve created a Repositories project that has references to EF4.3, DataLayer and DomainClasses.
Now I can use the context & repos as they are or take the generated code (which has saved me a lot of time) and tweak it to my needs. But this has taken a lot of the repetitive typing away from me and started me on a path of success. Happiness.
Thanks to Steve Sanderson & others who worked on this tooling!
(Oh and if you could modify the template to pull in “latest version of EntityFramework.dll”, that would be handy.)