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.)
Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!
This is so helpfull information, really saves time 🙂 it’s great, thanx.
Thanks for the tip! I was starting a new MVC project with EF4.3 and was running into compile errors – installing the current T4Scaffolding package solved my problems!
Few days ago, trying to share EF Code First between multiple projects, I had to figure out all that myself.
This great article will save a lot of time and provide people with kick-start.
Thank you Julie
Thanks for another great article.
We have a need to support user defined columns in many of our tables. How do we handle this via EF? My approach was to read|write these fields via ADO.net code (i.e double reads and double writes per table one via EF and one via ADO.net for User fields)….
There has got to be a better way than CustomTypeProvider, dynamic objects, etc.
I think that something is wrong with the generated repository. The Save() command must be managed by the UnitOfWork that call Save() for all repositories at once which will turn into a transaction.
This is great for building Domain Model based CRUD with the DbContext instead of the ancient (3-years old) ObjectContext. Where is the next step? Aren’t we supposed to map these objects/entities into a ViewModel or DTO instead of directly using the domain model?
Hi there! thank you for this great tutorial, however I am a bit confused here… You wrote: "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."
As you wrote I understand as if the Data layer depends on the Domain layer. Should’t it be the opposite in a n-tier application? I normally name my layers DataLayer and BusinessLogic layer, where in the later I reference the DataLayer, which means that The Business layer now depends on the data.
What am I mising here?
I am sorry, just a small correction for my previous comment: my data layer project is not called "DataLayer" but "DataAccess".
Also when I use the commad "et-PrimaryKey : Cannot find primary key property for type ‘HIS.BusinessLogic.Repositories.Question’. No properties appear to be primary keys."
What am I missing here?
Uh oh… so, again, here is my comment again, sorry, bad pasting!
Also when I use the command "scaffold repository HIS.BusinessLogic.Repositories.Question -DbContextType:HISDbContext", I get this message: "et-PrimaryKey : Cannot find primary key property for type ‘HIS.BusinessLogic.Repositories.Question’. No properties appear to be primary keys."
Any advice?
Same issue like Aleksander ,any help
Drawn back to this post and seeing some older comments
a) "but this isn’t perfect architectural design". No it’s not. It’s a great first step for people new to repositories. You can find a variety of templates on codeplex & nuget that go much further with the scaffolding. (Also keep in mind the age of this post!)
b) "wat! data in a business layer?" If your repository is part of your business layer then well, yes, and you probably don’t want that. The world is no longer a strict boundary of building apps with BLL & DLL. Shifting to this path of using repos, UOWs, thinkinga bout Domain Driven Design has really forced me to stop and consider where each piece of logic belongs. But that’s a MUCH larger discussion than what I was simply aiming for in this post. 🙂
c) errors…hmmm. There was an update to the nuget package about 7 months after I wrote this post. I’ts possible that the semantics of making calls has changed. I don’t know about troubleshooting this template. Sorry I can’t help but perhaps you’ll learn more in documentation or discussion on the nuget page for this package: nuget.org/…/MvcScaffolding
so far you are the best I seen describing EF.
Big no Huge Thank
We use our .net project fully based on t4Scaffold Template. So we have to automate this. Actually we tried to execute powershell command but scaffolding commands not working.
just like
“The term ‘T4Scaffolding’ is not recognized as the name of a cmdlet, function, script file, or operable program”
we got a help form this following link:
http://stackoverflow.com/questions/9049244/how-can-i-t4-scaffold-from-powershell-exe
but it is not working, Our requirement is to automate t4Scaffold and generated files move to another folder using jenkin.
If you have any idea to this, please let me know.
So sorry jivesh, but this kind of problem is definitely out of my scope of expertise.
This is sweet, I hated creating repos by hand 🙂