Thanks for reading...
Tuesday, March 22, 2011
Updated - MvcContrib UI Extensions - Themed Grid & Menu
After a comment on by blog here, I have updated the MvcContrib UI Extensions source code, the sample MVC3 Web application (both source and demo), and deployed a new NuGet package to the public NuGet feed. Here are the links:
Tuesday, March 15, 2011
Another Entity Framework 4 Repository & Unit of Work Solution–Intro and Part 4: ASP.NET MVC 3 Project
This is Part 4 in a series of posts that 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.
Below is the series outline; again, this is Part 4.
This will install StructureMap and register any assemblies with the Chinook.Web project. Once the NuGet command is executed, the NuGet Package Manager Console should echo the following: Go ahead and build the solution. Next, add the the new StructureMap reference to both the Chinook.Data.EF and Chinook.Infrastructure projects and rebuild the solution. Again, this series assumes that you have all the necessary tools (NuGet, POCO templates, etc…) installed with Visual Studio and that you are somewhat familiar with StructureMap. Now, remember the two files (EFRepositoryRegistry.cs.txt and ServicesRegistry.cs.txt) that the T4 templates generated for us in the previous post? We are going to use those files to create our StructureMap registries. The best way to do this is to create two new cs files in the respective projects, copy the code from the generated file, and paste it into these new code files. I understand this is not idea (copy, paste, etc…); however, I didn’t want to limit our solution to StructureMap only, so we’ll just have to deal with the awkwardness for now. So, create the following files and replace all the code in the new code file with the code in the associated generated file. Now we are going to invoke the StructureMap registration bootstrapping code from the Application_Start method of the Global.asax.cs file. Here’s the snippet: Go ahead and build the solution again… We are now going to create a quick controller, view, and some supporting View Models that will give a simple example how to use all the code created in this series of posts. For this part, go ahead and download the final solution. Logically representing the code here will be difficult and would provide little value without context; therefore, download the final solution and review the code in the Chinook.Web project. Here’s a quick list of the steps involved to generated the code samples:
Thanks for reading…
Below is the series outline; again, this is Part 4.
- 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.
- Core
- Infrastructure
- Web
PM> Install-Package StructureMap
- EFRepositoryRegistry.cs – in the Chinook.Data.EF project
- EFRepositoryRegistry.cs.txt – generated file
- ServicesRegistry.cs – in the Services directory within the Chinook.Implementation project
- ServicesRegistry.cs.txt – generated file
- StructureMapContainerSetup.cs – make this class static
- StructureMapDependencyResolver.cs
StructureMapDependencyResolver
using System; using System.Collections.Generic; using System.Linq; using System.Web.Mvc; using StructureMap; namespace Chinook.Web.Bootstrap { public class StructureMapDependencyResolver : IDependencyResolver { private readonly IContainer _container; public StructureMapDependencyResolver(IContainer container) { _container = container; } #region Implementation of IDependencyResolver /// <summary> /// Resolves singly registered services that support arbitrary object creation. /// </summary> /// <returns> /// The requested service or object. /// </returns> /// <param name="serviceType">The type of the requested service or object.</param> public object GetService(Type serviceType) { var instance = _container.TryGetInstance(serviceType); if ((instance == null) && !serviceType.IsAbstract) { _container.Configure(c => c.AddType(serviceType, serviceType)); instance = _container.TryGetInstance(serviceType); } return instance; } /// <summary> /// Resolves multiply registered services. /// </summary> /// <returns> /// The requested services. /// </returns> /// <param name="serviceType">The type of the requested services.</param> public IEnumerable<object> GetServices(Type serviceType) { return _container.GetAllInstances(serviceType).Cast<object>(); } #endregion } }
StructureMapContainerSetup
using System.Web.Mvc; using Chinook.Data.EF; using Chinook.Infrastructure.Services; using StructureMap; namespace Chinook.Web.Bootstrap { public static class StructureMapContainerSetup { public static void Setup() { IContainer container = new Container( x => { x.AddRegistry(new EFRepositoryRegistry()); x.AddRegistry(new ServicesRegistry()); } ); DependencyResolver.SetResolver(new StructureMapDependencyResolver(container)); } } }
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); StructureMapContainerSetup.Setup(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); }
- Create a ViewModel - AlbumGridItemViewModel.
- Create a IViewModelBuilder/ViewModelBuilder – IAlbumGridItemViewModelBuilder/AlbumGridItemViewModelBuilder.
- Create a new Controller - AlbumController.
- Use constructor injection to inject the ViewModelBuilder into the Controller - IAlbumGridItemViewModelBuilder into the AlbumController.
- Create a View to represent a list of ViewModel items – Index – this is only a list of items; however, the process remains the same for all types of views.
- Register the IViewModelBuilder/ViewModelBuilder with StructureMap – using a similar pattern as the other DI registrations – a StructureMap Registry.
Thanks for reading…
Labels:
ASP.NET MVC,
EF4,
Entity Framework,
Repository,
T4,
Unit of Work
Another Entity Framework 4 Repository & Unit of Work Solution–Intro and Part 3: Generated Code Review
This is Part 3 in a series of posts that 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.
Below is the series outline; again, this is Part 3.
IUnitOfWork.cs
The other Repository interfaces are just POCO specific Repository interfaces – man, that sounds really redundant…
The Services Interfaces – child-files of the Services.Interface.tt template are just empty service interfaces that you can add to as needed. Like the Repository interfaces, each POCO has it’s own Service interface.
Next, expand the Chinook.Infrastructure Project’s Services.Implementation.tt file. The code files generated by this T4 template are concrete implementation class of the aforementioned Service interfaces. There is a one-to-one relationship among the code generated interfaces to the code generated concrete implementations.
Next, expand the Chinook.Data.EF Project’s Repository.Implementation.EF.tt file.
As you can see, there is pretty much a one-one-relationship among the interfaces generated in the Chinook.Core/Repository to the concrete implementations here. Go ahead and spend some time looking over the generated files. The implementation for each is straight forward.
Beyond the Repository implementations, the following are notable files generated by the Repository.Implementation.EF.tt template:
As the name of the setting/variable and the associated comment suggests, this is an on/off switch for forcing code (re)generation. The default for this setting is false, meaning that if code is regenerated, the existing code will NOT be overwritten. So, let’s say that you create a custom email validator like the one in a previous post of mine - ASP.NET 3 Custom Validation. You manually decorate a few POCO properties in the POCO ‘buddy’ classes – the one containing metadata and data annotations – with the new email validator (e.g. Required(ErrorMessage = “Email is Required”)]. You have client-side and server-side validation working like a charm. Now, let’s say that your one or your database tables has changed and or you added a new table. You are going to want to regenerate all the classes and interfaces that the T4 templates created for you. No Problem! If you have the forceCodeGeneration settings set to false, your manual code changes will NOT get overwrittenand that hard work of yours will not need to be redone, or at a minimum, merged from the files in you source control system. You are using a source control system, aren’t you???
We will be using the code in these files in the next post in this series… Stay tuned…
In summary, we reviewed a few of the code files that the T4 templates generated, discussed how to NOT to overwrite your manual code changes to the generated files, and discovered how the T4 templates generate StuctureMap DI registration snippets and Registries for you.
In the next post in this series, we will put all the fruits of our labor (okay, the code generated labor) to use in an ASP.NET MVC 3 Web Application.
Thanks for reading…
Below is the series outline; again, this is Part 3.
- 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.
- IReadOnlyRepository.cs
- The IReadOnlyRepository is the base interface that all the entity specific interfaces inherit from. The IReadOnlyRepository contains (you guessed it…) read-only interfaces to the persistence layer.
- IRepository.cs
- The IRepository interface extends the IReadOnlyIRepository interface to include creating and deleting or entities.
- The original intent of separating the IReadOnlyRepository and IRepository interfaces was that so POCO object backed by data views (VIEWs on a database) would not inherit creating and deleting functionality.
- The IRepository interface extends the IReadOnlyIRepository interface to include creating and deleting or entities.
- IUnitOfWork.cs
- The IUnitOfWork interface handles all the transactions and changes needed to persist modifications to the persistence mechanism.
IReadOnlyRepository.cs
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; namespace Chinook.Core.Repository { /// <summary> /// Generic Read-Only Repository Contract /// </summary> /// <typeparam name="T"></typeparam> public interface IReadOnlyRepository<t> where T : class { /// <summary> /// Gets an IQueryable sequence of entities of type T. /// </summary> /// <returns></returns> IQueryable<t> Queryable(); /// <summary> /// Gets an IEnumerable sequence of all entites of type T. /// </summary> /// <returns></returns> IEnumerable<t> All(); /// <summary> /// Get an IEnumerable sequence of entities of type T filtered on the @where predicate. /// </summary> /// <param name="where">The where predicate.</param> /// <returns></returns> IEnumerable<t> Find(Expression<func><t bool ,>> where); /// <summary> /// Gets a single entity in a sequence of entities of type T using the filtered @where predicate. /// </summary> /// <param name="where">The where predicate.</param> /// <returns></returns> T Single(Expression<func><t bool ,>> where); /// <summary> /// Gets the first entity in a sequence of entities of type T using the filtered @where predicate. /// </summary> /// <param name="where">The where predicate.</param> /// <returns></returns> T First(Expression<func><t bool ,>> where); /// <summary> /// Gets a single entity (or default of entity of type T) in a sequence of entities of type T using the filtered @where predicate. /// </summary> /// <param name="where">The where predicate.</param> /// <returns></returns> T SingleOrDefault(Expression<func><t bool ,>> where); /// <summary> /// Gets a first entity (or default entity of type T) in a sequence of entities of type T using the filtered @where predicate. /// </summary> /// <param name="where">The where predicate.</param> /// <returns></returns> T FirstOrDefault(Expression<func><t bool ,>> where); } }
IRepository.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Chinook.Core.Repository { /// <summary> /// Generic Repository Contract. /// </summary> /// <typeparam name="T"></typeparam> public interface IRepository<t> : IReadOnlyRepository<t> where T : class { /// <summary> /// Adds the specified entity to the respository of type T. /// </summary> /// <param name="entity">The entity to add.</param> void Add(T entity); /// <summary> /// Deletes the specified entity to the respository of type T. /// </summary> /// <param name="entity">The entity to delete.</param> void Delete(T entity); /// <summary> /// Attaches the specified entity to the respository of type T. /// </summary> /// <param name="entity">The entity to attach.</param> void Attach(T entity); } }
namespace Chinook.Core.Repository { /// <summary> /// Unit of Work Contract /// </summary> public interface IUnitOfWork { /// <summary> /// Commits the changes to the data store. /// </summary> void Commit(); } }
- IObjectContext
- this is an interface that defines the contract used by the ObjectContextAdapter, the EFUnitOfWork, and ultimately the ObjectContext.
- ObjectContextAdapter
- this is a simple adapter class that wraps the Entity Framework’s ObjectContext object for use in the Repository/Unit of Work paradigm. This class implements the IObjectContext contract.
- RepositoryIQueryableExtensions
- this class includes a single method: Include. Include is an IQueryable(of T) extension method that affords the ‘Eager Loading’ functionality provided by the Entity Framework. But, since our solution abstracts the Entity Framework, the EF ‘Eager Loading’ Include method is not available. This extension method gives our solution the functionality back. You may not realize this yet, but that is a really cool ‘feature!’
- The implementation of this Include extension method was taken from the following article on MSDN: http://msdn.microsoft.com/en-us/ff714955.aspx – this is a great article and one that I got quite a few ideas for this series and solution.
- this class includes a single method: Include. Include is an IQueryable(of T) extension method that affords the ‘Eager Loading’ functionality provided by the Entity Framework. But, since our solution abstracts the Entity Framework, the EF ‘Eager Loading’ Include method is not available. This extension method gives our solution the functionality back. You may not realize this yet, but that is a really cool ‘feature!’
Template Force Code (Re)Generation – or NOT
Of this six T4 templates included in the download, all but the Domain.Poco.tt contain the following settings:// answers the question: Force generation of file even if the code file exists? bool forceCodeGeneration = false;
StructureMap configuration for Repositories and Services
If you’re reading this blog series, I’m sure you’re familiar with Dependency Injection (DI). There are quite a few DI containers for .NET; however, my favorite is StructureMap. Why is it my favorite? Well, when I first endeavored on the DI/IOC concept, StructureMap is what those around me recommended. I was not disappointed! The documentation could be better – it’s a little out-of-date; however, the DI API for StructureMap is extremely easy to use and relatively easy to understand. You will first need to overcome the DI/IOC paradigm challenges, but once the 'light goes on,’ you’ll wonder how you survived without it… Okay, back to the Bonuses… Expand the Repository.Implementation.EF.tt and Service.Implementation.tt T4 templates. Below are screenshots of the two T4 template generated outputs. Notice the highlighted files… All four of these files contain StructureMap Dependency Injection registration code. The files stating with __StructureMap.* contain ‘raw’ registration code that you can use however you’d like. The other two files (EFRepositoryRegistry.cs.txt and ServicesRegistry.cs.txt) contain StructureMap Registry derived classes. According to the StructureMap documentation, Registries are the recommended way to configure StructureMap:“The Registry DSL is the recommended way to configure StructureMap, and creating Registry classes is the recommended way of using the Registry DSL.”
We will be using the code in these files in the next post in this series… Stay tuned…
In summary, we reviewed a few of the code files that the T4 templates generated, discussed how to NOT to overwrite your manual code changes to the generated files, and discovered how the T4 templates generate StuctureMap DI registration snippets and Registries for you.
In the next post in this series, we will put all the fruits of our labor (okay, the code generated labor) to use in an ASP.NET MVC 3 Web Application.
Thanks for reading…
Labels:
ASP.NET MVC,
Entity Framework,
Repository,
T4,
Unit of Work
Another Entity Framework 4 Repository & Unit of Work Solution–Intro and Part 2: Creating the Repositories and Unit of Work (UoW)
This is Part 2 in a series of posts that 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.
Below is the series outline; again, this is Part 2.
As I mentioned above, the PowerShell file will generate T4 templates specific to your project. If you followed along in Part 1, these setting variables are taken from the namespaces that we specified in the last step. If you missed it, the following table duplicates our previous efforts:
The following are the project-specific settings:
Accept the ‘Execution Policy Change’ dialog message – the dialog only appears if you are using the editor. If you are using the non-editor PowerShell console, this ‘Execution Policy Change’ message will only echo to the console. Sorry about that little hiccup. If you’re not comfortable with setting the execution policy to 'unrestricted,’ you get reverse the policy back to ‘restricted’ once you’re done generating the necessary T4 templates by using the following PowerShell command:
For more PowerShell documentation, check out MSDN. Close the PowerShell editor. Okay, back to the tutorial… Once you execute the PowerShell script, the T4_EF4_Repository directory will now contain a new ‘Solution’ sub-directory and will contain six T4 templates with the project-specific settings defined earlier. These are the templates that we will be using in our application. Still with me? I hope so. I know – it’s a bit long the first time, but it’s really pretty simple and will be worth the effort. Hang in there… Next, if you haven’t already done so, open up the Chinook Visual Studio Solution. We are now going to add the POCO generator to the EF Data Model. If you don’t have the ADO.NET POCO Entity Generator template installed, you will need to add it via the Visual Studio Extension Manager from the Visual Studio Gallery.
For each one of the following directories in the list above, add the associated T4 template in listed order by right-clicking the respective directory, clicking ‘Add / Existing Item…’, navigating to the T4_EF4_Repository/Solution directory (in the root of the solution) and selecting the associated T4 template. A couple of notes…
Build the solution again. All the dependencies should now be resolved and the solution should build with no errors. In summary, we walked 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 using T4 templates to generate the code using our EF data model
In the next post in this series, we will review a few of the generated class/interfaces that the T4 code generation templates created.
Thanks for reading…
Below is the series outline; again, this is Part 2.
- 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.
- Domain.Poco.tt
- This template generates the POCO (Domain) classes from your EF data model.
- Domain.Poco.Metadata.tt
- This template generates data annotations/metadata ‘buddy’ classes for the POCOs.
- Repository.Interface.tt
- This template generates all the associated Repository Interfaces/Contracts, including:
- base IReadOnlyRepository and IRepository Interfaces
- IUnitOfWork Interface
- I<POCO_ClassName>Repository Interface for each POCO class generated from you EF data model.
- base IReadOnlyRepository and IRepository Interfaces
- This template generates all the associated Repository Interfaces/Contracts, including:
- Repository.Implementation.EF.tt
- This template generates the EF-related concrete class implementations defined by the IRepository Interfaces/Contracts.
- Services.Interface.tt
- This template generates a light-weight Service Interfaces/Contracts for each POCO class.
- Services.Implementation.tt
- This template generates the concrete class implementation defined by the Service Interfaces/Contracts.
- prepareT4Templates.ps1
- This is just a simple PowerShell script that contains project-specific settings to assist in generation T4 templates specific to the project – in our scenario, the Chinook application solution.
#***************************************************************** #***************************************************************** #*********** BEGIN Template Parameters *************************** #***************************************************************** # path to the project's edmx data model (entity framework data model) $edmxFilePath = "..\..\Chinook.Data.Ef\Chinook.edmx" # the namepace name where the solution's domain models live $domainModelNamespace = "Chinook.Core.Domain" # the namespace name where the solution's services will live $serviceInterfaceNamespace = "Chinook.Core.Services" # the namespace name where the solution's repository will live $repositoryInterfaceNamespace = "Chinook.Core.Repository" #***************************************************************** #*********** END Template Parameters ***************************** #***************************************************************** function createDirectory($directory){ New-Item $directory -type directory -force } function removeDestinationFile($file){ if(Test-Path $file){ Remove-Item $file } } function writeout($file){ $sourceFile = "Source/" + $file $destinationDirectory = "Solution/" $destinationFile = $destinationDirectory + $file createDirectory($destinationDirectory) removeDestinationFile($destinationFile) (Get-Content $sourceFile) | Foreach-Object {$_ -replace "\[\*\*EDMX_FILE_PATH\*\*\]", $edmxFilePath} | Foreach-Object {$_ -replace "\[\*\*DOMAIN_MODEL_NAMESPACE\*\*\]", $domainModelNamespace} | Foreach-Object {$_ -replace "\[\*\*SERVICE_INTERFACE_NAMESPACE\*\*]", $serviceInterfaceNamespace} | Foreach-Object {$_ -replace "\[\*\*REPOSITORY_INTERFACE_NAMESPACE\*\*\]", $repositoryInterfaceNamespace} | Set-Content $destinationFile } $files = @("Domain.Poco.tt", "Domain.Poco.Metadata.tt", "Repository.Interface.tt", "Service.Interface.tt", "Repository.Implementation.EF.tt", "Service.Implementation.tt") foreach($file in $files){ writeout($file) }
Directory | Namespace |
Domain | Chinook.Core.Domain |
Repository | Chinook.Core.Repository |
Services | Chinook.Core.Services |
- $edmxFilePath
- relative path to the solution’s EF data model (edmx)
- $domainModelNamespace
- the namespace where the solution’s POCO’s live – see namespace table above
- $serviceInterfaceNamespace
- the namespace where the solution’s Service Interfaces/Contracts live – see namespace table above
- $repositoryInterfaceNamespace
- the namespace where the solution’s Repository Interfaces/Contracts live – see namespace table above
File C:\Chinook\T4_EF4_Repository\prepareT4Templates.ps1 cannot be loaded. The file C:\Chinook\T4_EF4_Repository\prepareT4Templates.ps1 is not digitally signed. The script will not execute on the system. Please see "get-help about_signing" for more details..
You have a couple choices to get around this, but the easiest is to set the PowerShell execution policy to ‘unrestricted’ using the following PowerShell command (* you must be running PowerShell as an Administrator). Go ahead and run this command in the PowerShell console in the bottom pane of the PowerShell editor:
Set-ExecutionPolicy UnRestricted
Set-ExecutionPolicy Restricted
Adding the POCO Template
- Open up the Chinook.edmx file so the EF data model is visible in the designer (this is located in the Chinook.Data.EF project)
- Right-click on an empty area of the EF data model canvas and select ‘Add Code Generation Item…’
- This will bring up the ‘Add new Item Dialog,’ in which you will choose the ADO.NET POCO Entity Generator template (via the Installed Templates –> Code node)
- Set the ‘Name’ of the ADO.NET POCO Entity Generator item to ‘Poco.tt’
- Save the EF data model (edmx file) and build the Chinook.Data.EF project.
- Delete the Poco.tt file from the Chinook.Data.EF project
- ** DO NOT delete the Poco.Context.tt file.
Add the T4 Templates to the Solution
We are now going to add the T4 templates that we generated earlier.Project | Directory | T4 Template (Solution directory) |
Chinook.Core | Domain | Domain.Poco.tt |
Chinook.Core | Domain | Domain.Poco.Metadata.tt |
Chinook.Core | Repository | Repository.Interface.tt |
Chinook.Core | Services | Service.Interface.tt |
Chinook.Data.EF | * add using Project node * | Repository.Implementation.EF.tt |
Chinook.Infrastructure | Services | Service.Implementation.tt |
- You may need to use the ‘All File(*.*)’ filter on the ‘Add Existing Item’ dialog.
- Ensure that you select the proper T4 templates (e.g. use the ‘Solution’ directory and NOT the ‘Source’ directory)
Build the Solution and Resolve Dependencies
Now, go ahead and build the solution and resolve any dependencies that appear in the Error List. You will get errors on the ‘ObjectContext’ derived class (ChinookEntities in our scenario). To resolve these errors, you will need to add a reference to the Domain namespace where the POCOs classes live (we identified this earlier in the ‘namespace’ table). In our scenario, just add the following using statement to the ‘ChinookEntities’ class…using Chinook.Core.Domain;
In the next post in this series, we will review a few of the generated class/interfaces that the T4 code generation templates created.
Thanks for reading…
Labels:
ASP.NET MVC,
EF4,
Entity Framework,
Repository,
T4,
Unit of Work
Thursday, March 10, 2011
Another Entity Framework 4 Repository & Unit of Work Solution–Intro and Part 1: Setup
Entity Framework Code First (EF Code First) has been getting quite a bit of press lately. I’ve done some ‘play’ development using EF Code First; however, the powers that be seem to keep bringing me back to the Model First (create database/ERD and then the application code) paradigm.
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:
In summary, we’ve created a new database, created a new Visual Studio application solution and project structure, and generated an Entity Framework data model from an existing database.
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…
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…
Labels:
ASP.NET MVC,
EF4,
Entity Framework,
Repository,
T4,
Unit of Work
Subscribe to:
Posts (Atom)