What I really like about EF Code First is the seamless use of Separation of Concerns. My next few posts are going to be a series of entries on using the Model First approach to take advantage of Separation of Concerns.
Rather than discuss software development and design theory, these posts will walk through the process of implementing a solution that separates concerns into specific behaviors using the Entity Framework 4 and the Repository and Unit of Work Patterns. To facilitate this process, we will be using T4 templates.
While there are many solutions online that create similar implementations, this series will focus on a process that I really like, fits my needs, and is easy to understand. That last point is important – ‘easy to understand.’ Separation of Concerns and all the concepts that come along with it can be very overwhelming if you’re coming from ASP.NET Web Forms…
Forewarning – this series of posts contain quite a few steps. I considered creating a NuGet package; however, I couldn’t settle on the structure of the package and I realized that I started losing focus on the intent of my madness. I also considered creating a few Visual Studio templates; however, my experience with VS templates is limited, and once again the madness had me losing focus. That said, hopefully this series and the steps involved will not be too overwhelming. I feel the value of the final results far exceed the steps involved in getting there…
UPDATE: the NuGet team is considering adding functionality where NuGet could be run from PowerShell outside of Visual Studio. This means that one could create a NuGet package that would create a solution with x number of projects and add dependencies to those projects, files, etc… If that functionality was available now, I could deploy all the steps involved here in a single NuGet package – eliminating MOST of the steps on this series. If this sounds cool – it is cool – vote for this functionality here.
Okay, so here is the series breakdown:
- Part 1: Setup
- This post involves downloading and creating the SQL Server database, setting up the Visual Studio solution and project structure, and generating the out-of-the-box Entity Framework (EF/EF4) data model from the newly created database.
- Part 2: Creating the Repositories and Unit of Work (UoW)
- This is the meat of the series. This post includes downloading some T4 templates, settings a few parameters, and generating the Repositories and Unit of Work (UoW) using the T4 templates and EF4 data model.
- Part 3: Review Some of The Generated Code
- This post will review a few of the generated class/interfaces that the T4 code generation created.
- Part 4: Using EF, Repository & UoW in an ASP.NET MVC 3 Project
- This post includes wiring up the EF4 data model, repositories, and UoW to StructureMap dependency injection container and use of these products in an ASP.NET MVC 3 Web application project.
Part 1: Setup
As stated above, in Part 1 we are going to create a database, create a Visual Studio solution and project structure, and generate an EF4 data model that points to our database.1) Create a database
For this series, we are going to use the Chinook database. Specifically, we are going to use the Chinook version 1.2 for SQL Server. You can download the Chinook database from CodePlex – make sure you download version 1.2 – in preparing for this series, I had issues generating EF4 Navigation Properties with Chinook version 1.3, so please use version 1.2. The download contains two SQL scripts for generating the Chinook database. Please use the SQL Script that generates table primary keys with IDENTITY. Once the Chinook database is generated, the database should similar to the following screenshot from SQL Server Management Studio (SSMS):2) Visual Studio Solution and Project Structure
The solution and related projects architecture that we are going to use loosely follows the Onion Architecture Pattern – this is a great read and well worth the time…- Create an empty Visual Studio Solution.
- Open Visual Studio
- Click ‘File’ –> ‘New’ –> ‘Project’
- Under the ‘Installed Templates,’ select the ‘Other Project Types’ node in the project tree, select the ‘Visual Studio Solutions’ node, and then select the ‘Blank Solution.’ Name the solution ‘Chinook.’ Here’s a screenshot of the New Project Wizard:
- Open Visual Studio
- Create the following three Class Library Projects. Delete the auto-generated ‘Class1.cs’ file that was added to each project.
- Chinook.Core
- See details in the next step
- Chinook.Data.EF
- This is where the Repository Implementations and Unit of Work classes will live.
- Chinook.Infrastructure
- This is where the Service Implementations will live.
- Chinook.Core
- Create the following three directories within the Chinook.Core Project:
- Domain
- This is where the Domain Model object will live.
- Repository
- This is where the Repository Contracts will live.
- Services
- This is where the Service Contracts will live
- Domain
- Create the following directory within the Chinook.Infrastructure Project:
- Services
3) Generate an EF4 Data Model from an Existing Database
Right-click the Chinook.Data.EF Project and select ‘Add / New Item…’ Next, select ADO.NET Entity Data Model from the Data Templates list, name it ‘Chinook,’ and click ‘Add’ Next, select ‘Generate from database’ and click ‘Next’ Now it’s time to point the EF Data Model to the Chinook database created in step ‘1) Create a Database.’ Go ahead and locate your database (or create a New Connection) and make sure that it is selected in the database drop-down-list. Also, click the ‘Save entity connection settings in App.Config as:’ checkbox and leave the default Connection settings name. Next click ‘Next.’ Next, choose the database object that you want to model. For this series, just choose the ‘Table’ objects by selecting the checkbox next to the ‘Tables’ node. Click both of the checkbox options and the default Model Namespace and click ‘Finish.’ The result is the EF data model that points to the 'Chinook’ database – Chinook.edmx Save the file and build the Chinook Solution. A few more steps before we wrap Part 1 up…- Add a reference to the ‘System.ComponentModel.DataAnnotations’ assembly to the Chinook.Core project.
- Add a reference to the Chinook.Core project to the other two projects: Chinook.Data.EF and Chinook.Infrastructure
- Make note of the namespaces of the following three directories within the Chinook.Core project – you will need these for Part 2 of the series
Directory | Namespace |
Domain | Chinook.Core.Domain |
Repository | Chinook.Core.Repository |
Services | Chinook.Core.Services |
In the next post in this series, we’ll walk though the steps of creating Plain Old CLR Objects (POCOs) Repositories, Services, and a Unit of Work (UoW) using some T4 templates to generate all the aforementioned code.
Thanks for reading…
6 comments:
Thanks a lot Ryan. This really helped me a lot. Great detailed approach for beginners.
Could you Provide a basic sample implementation for WebForms? as IDependencyResolver seems to be an MVC 3 concept.
Thank You.
Thanks for the comment Akhil. The concept of Dependency Injection is a bit convoluted in Web Forms as Web Forms Page and User Controls (via Page/UserControl classes) do not support constructor injection. You could potentially use property injection or just instantiate objects like you would normally do; however, this approach is not conducive to unit testing. The following contains a couple of snippets for DI registration in non-IDependencyResolover supported scenarios: Link. I hope this helps...
Sure, it did. Thank You.
Also, i have a requirement where in the Object Context Provider Connection String needs to be based on User Login (using Forms Authentication, and membership). Is there a Thread Safe way (per HTTP Request) to Inject Dependency Dynamic Connection String From Session?
Thanks.
I suppose your scenario is possible via structuremap's constructor (with parameters) injection; however, I don't recall ever injecting parameters (FWIW - that's a very odd requirement - per-user connection string). EF Object Context requires metadata (used for ORM mapping) in the connection string, making property injection a bit more challenging. I believe structuremap also supports parameterized strings, so you could have a connection string with {0} -based templates (containing the full connection string with {0} templates for the respective user name/id) and inject the user with string.Format. I recommend that you throw a question out on StackOverflow presenting your specific (or similar) scenario. I know that doesn't specifically answer your question, but hopefully that points you in the right direction. Good luck Akhil... -Dan
Sorry to Bug You, but i have one more question on the Article (im an absolute beginner to EF4, SoC paradigm).
So, The EF4_T4 template Generates IServices in Core proj and The Infrastructure Project implements those. So, according to DDD, do i assume Infrastructure is my BLL, and implement a Constructor with Respective IRepositiory and initialize it as done in Web-> Models - > Albums -> AlbumGridViewModelBuilder.cs?
Essentially i need to provide Concrete implementation for Services in the Infrastructure Project and use them in my Web Pages?
Post a Comment