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.
Now on to Part 4… Open up the Chinook solution in Visual Studio. Let’s do a little solution organization.  Create the following three solution folders by right-clicking the solution file, selecting ‘Add,’ and then selecting ‘New Solution Folder.’ image
  • Core
  • Infrastructure
  • Web
Place the Chinook.Core project into the Core Solution Folder and place the other two projects (Chinook.Data.EF and Chinook.Infrastructure) into the Infrastructure Solution Folder.  The Web Solution Folder will contain our MVC Web application project.  Let’s do that now… Right-click the Web Solution Folder.  Click 'Add’ –> ‘New Project…’ image Next, create an ASP.NET MVC 3 Web Application and name is ‘Chinook.Web’ and click ‘OK.’ image On the next screen, select ‘Internet Application,’ the ‘Razor’ View engine, and click ‘OK’ image Right-click the new ‘Chinook.Web’ Application Project and select ‘Set As Startup Project.’  The solution structure should now look similar to the following: image Add the following References to the ‘Chinook.Web’ Project and then build the solution. image In the description of this post, it states that we are going to use StructureMpa as our DI container.  We are going to get StructureMap via NuGet.  Assuming you have NuGet installed, select the Chinook.Web project, open the ‘Package Manager Console,’ and type the following command:
PM> Install-Package StructureMap
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: image 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.
  • 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
Go ahead and build the solution again. Next, we are going to register our repositories, unit of work, and other dependencies (created earlier in a previous post) with StructureMap in our Chinook.Web project.  To do this, we are going to use ASP.NET MVC 3 IDependencyResolver – you can read about IDependencyResolver here and read the API docs here. Create a ‘Bootstrap’ directory in the Chinook.Web project and create the following two empty code/class files:
  • StructureMapContainerSetup.cs – make this class static
  • StructureMapDependencyResolver.cs
Now we are going to register the Registries created earlier in these ‘bootstrap’ files.  Since this series of posts is walk through on the process of setting up a solution for separation of concerns and not on the theory of such topics, the exercise of explaining the StructureMap registration is beyond the scope of this series.  Populate these newly created code files with the following content:
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));
        }
    }
}
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:
protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    StructureMapContainerSetup.Setup();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}
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:
  1. Create a ViewModel - AlbumGridItemViewModel.
  2. Create a IViewModelBuilder/ViewModelBuilder – IAlbumGridItemViewModelBuilder/AlbumGridItemViewModelBuilder.
  3. Create a new Controller - AlbumController.
  4. Use constructor injection to inject the ViewModelBuilder into the Controller -  IAlbumGridItemViewModelBuilder into the AlbumController.
  5. 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.
  6. Register the IViewModelBuilder/ViewModelBuilder with StructureMap – using a similar pattern as the other DI registrations – a StructureMap Registry.
The resulting list generated in the sample code is not designed for performance (e.g. no paging, sorting, etc..).  In production, this type of code can and should be refactored.  That said, the key points throughout this series are the patterns used to create a solution based on separation of concerns – including the Repository and Unit of Work patterns and using StructureMap as a Dependency Injection container.

Thanks for reading…

21 comments:

Muhammad Azeem said...

This is a nice article..
Its very easy to understand ..
And this article is using to learn something about it..

c#, dot.net, php tutorial

Thanks a lot..!

Akhil Parasa said...

Could you Provide a basic sample implementation for WebForms? as IDependencyResolver seems to be an MVC 3 concept.

sfuptown said...

Great Article!

I love the idea, however in your MVC example you only show how to display data. I'm trying to figure out how to save and update using your repository and can't figure it out. This is a new way of thinking and one I think is well worth it, but my head is spinning. Can you please show some example code in the MVC app that demonstrates how to create,edit and save in a manner similar to the IModelViewBuilder.

Many Thanks

tdryan said...

Hello @sfuptown. Great question. I forgot to add how to create/edit/delete using this solution.

The UnitOfWork is what commits all changes to the data store. Martin Fowler's definition: 'Maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.'

This is is what I use the Service (IServicePOCOENTITY) for. Basically, you create an implementation of one of the IServicePOCOENTITY interfaces that injects the necessary repositories and the UnitOfWork. Then you inject this service into you controller and register the DI with StructureMap. Rather than post an example here, I will update the sample project later today. Check back later today. I will update the sample with the aforementioned solution.

If you start to get confused with all the classes and interfaces, the key is to remember that the purpose of all this is for Separation of Concerns and Unit Testing.

Hope that helps...

sfuptown said...

Yes, thank you for the quick response. This is exactly what I was looking for! This sort of brings it all together so I am learning the benefits of this type of architecture. And your solution is very clean and easy to understand. Great Job!

I did have one other question which I was hoping you could help on as I'm stuck. I'm porting some web forms code to an mvc site. This code has its own authentication rather than using .net membership. So in the global.asax.cs file Application_AuthenticateRequest event it calls this code:

FormsAuthentication.GetCachedAuthenticationManagerAndLogin(true, true);

Within this static function
FormsAuthentication.GetCachedAuthenticationManagerAndLogin, it creates an AuthenticationManager object passing in a dbConn. I am trying to do the same thing substituting the IMemberService.

So I changed the constructor of the AuthenticationManager to take an IMemberServive rather than a dbConn, like so:

mgr = new AuthenticationManager(_memberService);

and the constructor of the AuthenticationManager is such:

public AuthenticationManager(IMemberService memberService)
{
_memberService = memberService;
}

The problem is I have no control over the Application_AuthenticateRequest event signature and have no way of injecting the IMemberService in the constructor.

Basically the signature is this:
protected void Application_AuthenticateRequest(Object sender, EventArgs e)

and I would want it to be this:
protected void Application_AuthenticateRequest(Object sender, EventArgs e, IMemberService s)

Obviously I can't do this. So the challenge is how to get this to work? Can you think of the solution? If so, I would be grateful as I am super stuck!

Many Thanks


Many Thanks

tdryan said...

That's what you call Method Injection. I haven't done this before (not do I know if StructureMap supports this), but off the top of my head, I recommend trying the following:

1) Register your IMemberService DI with the StructureMap container.
2) In the Application_AuthenticateRequest event handler, initialize the IMemberService implementation using StructureMap's ObjectFactory:
e.g. var memberService = ObjectFactory.GetInstance<IMemberService>();
3) Then just use the IMemberService implementation with you AuthenticationManager constructor.

That, with a little modification, should give you what you need.

There's also the concept (actually reality) of WebActivator activation; however, I've only been a consumer of this technology, so I cannot give any advice on the implementation.

If this doesn't work or you're stuck on something, try searching StackOverflow, or post a question of StackOverflow. This is pretty much the best source out there.

Good Luck...

sfuptown said...

Thanks for the quick response.

Just need to clear up a few things:

Isn't this done already?
Register your IMemberService DI with the StructureMap container.

using your template bonus code in
ServicesRegistry.cs
For().Use();

Or is there an additional entry that needs to be made in structureMap?

As is, it doesn't work, the object is null.

Thanks

tdryan said...

You're right - the IMemberService is already registered with SM via the ServicesRegistry. Without viewing your code, I didn't realize that this was part of the generated code and the associated developer generated implementations. So, take out step 1. Steps 2 and 3 should remain the same. This should work.

You mentioned that your IMemberService implementation is null??? DI registration fires in the Application_Start event hander, and since Application_Start fires before Application_AuthenticateRequest, the ObjectFactory.GetInstance<IMemberService>() should work just fine. If you are still having trouble (null object), check your implementation of IMemberService. You may also want to do a debug walk-through on the DI registration and make sure your IMemberService registration is registered correctly.

sfuptown said...

Thanks again for your quick response and for trying to help.

I just couldn't get it working with stucturemap, so swapped it out for ninject and it worked on the first try with no tweaking necessary.

Thanks again for a great blog post on an important topic. I've learned a lot from it and it has made me a better developer.

tdryan said...

@Sfuptown - happy you figured it out. Very cool that you plugged Ninject in as the DI container. That was the purpose behind the StructureMap Registry classes generated as optional code. I hope the switch was relatively painless. Thanks for the feedback, and I'm happy that you learned something...

sfuptown said...

Subtle Bug? or am I missing something?

I am using the templates and all is going well. Then I run into unexpected behavior. I'll explain...

I have 3 tables
1. Member table
2. EmailRecipient table. Member table stores the EmailRecipientId via association.
3. PostalCode table. Member table stores the PostalCodeId via association.

Pretty basic set of 3 tables.

I have a multi-step registration process.
1. Step 1, user enters email so I create a new member poco object. Also create a new EmailRecipient to store the email.

Code is straight forward:
var m = new Core.Domain.Member()
{
CreateDate = DateTime.Now,
Birthdate = data.DOB.Value,
Gender = (byte)data.Gender.SelectedItemId,
MemberStatus = (int)MemberStatusFlags.IncompleteProfile
};

m.EmailRecipient = new EmailRecipient();
m.EmailRecipient.SmtpAddress = data.Email;

This works fine. A new Member record and associated EmaailRecipient record is stored in the DB as exptected.

Step 2. (This is where the issue is)
Member enters Postal Code so...

1. I load the Member from the DB.
2. Create a new PostalCode object exactly how I created the EmailRecipient object in the previous step.

var f = _memberRepository.FirstOrDefault(m => m.MemberId==memberId);
if (f != null)
{

f.PostalCode = new PostalCode();

This throws a NullReferenceException on this line in the Member.cs poco object in this method:
private void FixupPostalCode(PostalCode previousValue)
.....
last lines in method attempt to sync up the PostalCodeId with the new value PostalCodeId

if (PostalCodeId != PostalCode.PostalCodeId)
{
PostalCodeId = PostalCode.PostalCodeId;
}

PostalCodeId is a nullable int and is null. This line:
PostalCodeId = PostalCode.PostalCodeId; throws the null reference exception.

Works fine for the EmailRecipient in previous step. Only difference is in first step I am creating a new Member and this step I am loading the Member.

Now, if a nullable int is null, it should be able to get a value assigned to it?

Did I discover a subtle bug or am I missing something? Have you run into this issue?

Many Thanks

tdryan said...

The FixupPOCO method is boilerplate code taken from the Microsoft POCO tt template - I didn't modify that part of the code. You've probably already realized this, but the purpose of this method is to wire up object references and primary keys (IDs). Your code looks valid; however, without direct access to walk-through your code, it will be near impossible for me to determine the issue. Focus in on the null reference exception - try creating a PostalCode object, persist that object, and then attach it to your Member object. The sample/demo project contains similar nullable int to non-nullable int control statements to wire-up the primary keys. Take a look at one of these (e.g. Employee and SupportRepId properties of the Customer class). As for ever running into this issue... I've been using the templates for awhile, and I haven't experienced similar issues.

sfuptown said...

Thanks for the quick response!

I did a small hack to get it to work. When a new object is added, i.e. the PostalCode, the primary key gets an id of 0. So, to short circuit that line of code, I added this line before creating the new PostalCode

f.PostalCodeId = 0;
f.PostalCode = new PostalCode()

Now the check in the sync will be equal and the offending line will be skipped. It's a bit of a hack, but it works. :)

What sample code are you referring to? In the download, the only code I see is for Album?

sfuptown said...

Whats even more interesting is that it lets me assign the value to 0 before creating the object. However, the line that causes the error is doing the exact same thing...assigning the value of the newly created object of 0 to PostalCodeId.

Not sure why it is ok with doing it manually first? Any thoughts?

tdryan said...

f.PostalCodeId is only a property, so assigning it a value if fine - even if there is not associated object - but, that's not the recommended way, because the synch is out-of-synch. Notice the _settingFK field? This is a flag used to manage the synch. That said, this is what the FixUp code is doing. Recall that an int value type has a default value of 0. EF also uses an object with a primary key of 0 to determine if the object is an INSERT or UPDATE. I don't know why your code is throwing an exception...

sfuptown said...

Hey, thanks again for your response. Just wanted to let you know I figured out the issue. Seems it is not a bug, but my bad.

The PostalCode object has a StateId field which links to the State table. I was just setting the StateId and didn't realize I need to also set the State property. Once I set that property on the PostalCode object, the line that through the exception works fine.

The tricky part was that NullRefException. Since it happened on that line I assumed it was PostalCodeId field. However, the State property was null and that was causing the exception.

Thanks again!

sfuptown said...

This is a great article and I've been using it on a project. So far, its working great! However, I've come to a point in the project where I need to use some stored procs. Uh oh, I knew this would happen. :)

Anyway, since the idea is to abstract away the data context, it makes no sense to use it to call stored procs, but not sure how to do it.

I was thinking about using BL Toolkit for the procs. Is there a way to plug this into your design? Or is there another way?

If you don't have time to update the article, can you please update the sample project to show how to use stored procs to retrieve data.

Many Thanks for great work.

tdryan said...

Hello @Sfuptown:

I haven't tried using stored procs with this solution. I actually haven't used my solution in some time, so I'm afraid that I can't help you much. I'm not familiar with BL Toolkit; however, if this fits your need, then give it a try. You also may want to use the old fire hose solution - data readers - to pull data from the database via stored procs. The tried and trued Microsoft.ApplicationBlocks.Data.SqlHelper is also still a great solution and still viable.

Hope that helps...

sfuptown said...

Hi, thanks for the reply.
Though its disappointing that you can't help.

Is there a reason you haven't been using this? Have you moved on to something better?

Thanks

tdryan said...

I've been using the newer and simplified Entity Framework 4.1 Context object - DbContext. MVCScaffolding uses this, as do other T4 tempates. It's the way that most folks are moving. That said, the code from the blog post using ObjectContext is still very relevant.

The idea behind the post was to get those unfamiliar with various Separation of Concerns patterns a little more comfortable: IoC, Repository, Unit Of Work, etc...

As for your stored proc and related mapping/marshalling code... Don't box yourself into one data access technology. It is NOT bad design to have more than one data access methodology. What is bad design is trying to manipulate something when something else is preferred. While EF and the abstractions it provides are a huge asset, it does have it's cons (e.g. reflection). As I mentioned in the previous comment, I actually prefer to use Microsoft.ApplicationBlocks.Data.SqlHelper when accessing stored procs.

So, while the the post and the related templates give you 90+ percent of what you need, it's not the only solution around. Focus on what the solution provides and adapt to design the pieces that it doesn't.

Have you ever used CodeSmith Generator? I use this code generation tool all the time. If you haven't tried it, I highly recommend it. CodeSmith Generator is a much more advanced code generation tool. Out-of-the-box it contains many code generation template. There is also a CodeSmith community that has many more great code generation template. CodeSmith even integration well with Visual Studio. Is is not free, but it is worth every cent. If you're interested, here's the link CodeSmith Tools.

phil n said...

Great article.

I wonder if you're thinking of creating a similar series using Entity Framework 4.1 and DbContext?

Thanks again