A day with .Net

My day to day experince in .net

Design an MVC application Using Enity Framework Repository Pattern, Unit Of Work Pattern and Dependency Injection

Posted by vivekcek on June 10, 2013

In this post, I am going to present how to design an MVC application Using Enity Framework Repository Pattern, Unit Of Work Pattern and Dependency Injection.

I hope the reader is aware of the basics of MVC, Entity Framework, Repository Pattern, Unit Of Work Pattern and Dependency Injection. Because in this post, i am only concentrating on practical implementation.

What is Entity Framework?

Entity Framework (EF) is an object-relational mapper that enables .NET developers to work with relational data using domain-specific objects.It eliminates the need for most of the data-access code that developers usually need to write.

The Repository and Unit of Work Patterns?

The repository and unit of work patterns are intended to create an abstraction layer between the data access layer and the business logic layer of an application. Implementing these patterns can help insulate your application from changes in the data store.

Creating a repository class for each entity type could result in a lot of redundant code, and it could result in partial updates. For example, suppose you have to update two different entity types as part of the same transaction. If each uses a separate database context instance, one might succeed and the other might fail. One way to minimize redundant code is to use a generic repository, and one way to ensure that all repositories use the same database context (and thus coordinate all updates) is to use a unit of work class.

The unit of work class coordinates the work of multiple repositories by creating a single database context class shared by all of them.

2

Why Need to Inject Controller Dependency?

In real life application development, you will see almost all ASP.NET MVC applications are needed to inject its dependent component. You can create component directly inside the controller instead of inject them. In that case the controller will be strongly coupled on those components. If any component’s implementation is changed or new version of that component is released then you must change controller class itself.

End Of Theory

The example i am using is a small Blog Engine concept, Which include 3 domain objects ‘Blog’, ‘Post’ and ‘Comment’.

Look at the solution structure. Please note the Class library names.

1

1. Create 3 domain classes ‘Blog’, ‘Post’, ‘Comment’ in ‘BlogEngine.Model’ Library. Don’t forgot to install Entity Framework Nuget Package. Also do look at the namespaces.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;
namespace BlogEngine.Model
{
    public class Blog
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int BlogId { set; get; }

        [Required,StringLength(500)]
        public string BlogName { set; get; }

        public virtual ICollection<Post> Posts { get; set; }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace BlogEngine.Model
{
    public class Post
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int PostId { get; set; }

        [Required]
        public string Title { get; set; }

        [Required]
        public string Content { get; set; }

       
        public int BlogId { get; set; }

        [ForeignKey("BlogId")]
        public Blog Blog { get; set; }

        public virtual ICollection<Comment> Comments { get; set; }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace BlogEngine.Model
{
    public class Comment
    {
        [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int CommentId { get; set; }

        [Required]
        public string Content { get; set; }
    }
}

2. Create a Generic Repository Interface ‘IRepository’ in ‘BlogEngine.Data.Contract’ Library.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace BlogEngine.Data.Contract
{
    public interface IRepository<T> where T : class
    {
        IQueryable<T> GetAll();
        IQueryable<T> Find(Expression<Func<T, bool>> predicate);
        T GetById(int id);
        void Remove(T entity);
        void Add(T newEntity);
    }
}

3. Implement this ‘IRepository’ interface in ‘BlogEngine.Data’ Library as ‘BlogEngineRepository’.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlogEngine.Data.Contract;
using System.Data.Entity;

namespace BlogEngine.Data
{
    public class BlogEngineRepository<T> : IRepository<T> where T : class
    {
        protected DbContext DbContext { get; set; }
        protected DbSet<T> DbSet { get; set; }

        public BlogEngineRepository(DbContext dbContext)
        {
            if (dbContext == null)
            {
                throw new ArgumentNullException("dbContext");
            }
            else
            {
                DbContext = dbContext;
                DbSet = DbContext.Set<T>();
            }
        }

        public IQueryable<T> GetAll()
        {
            return DbSet;
        }

        public IQueryable<T> Find(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
        {
            return DbSet.Where(predicate);
        }

        public T GetById(int id)
        {
            return DbSet.Find(id);
        }

        public void Remove(T entity)
        {
            DbSet.Remove(entity);
        }

        public void Add(T newEntity)
        {
            DbSet.Add(newEntity);
        }
    }
}

4. Create a DbContext class named ‘BlogEngineDbContext’ in ‘BlogEngine.Data’.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using BlogEngine.Model;

namespace BlogEngine.Data
{
    public class BlogEngineDbContext:DbContext
    {

        public BlogEngineDbContext()
            : base("name=BlogEngineDbContext")
        {

        }
        public DbSet<Blog> Blogs { get; set; }
    }
}

5. Create a Unit Of Work Interface named ‘IBlogEngineUnitOfWork’ under ‘BlogEngine.Data.Contract’.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlogEngine.Model;

namespace BlogEngine.Data.Contract
{
    public interface IBlogEngineUnitOfWork
    {
        void Commit();
        IRepository<Blog> Blogs { get; }
    }
}

6. Implement ‘IBlogEngineUnitOfWork’ in ‘BlogEngine.Data’.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BlogEngine.Data.Contract;
using BlogEngine.Model;

namespace BlogEngine.Data
{
    public class BlogEngineUnitOfWork : IBlogEngineUnitOfWork, IDisposable
    {
        private BlogEngineDbContext DbContext = null;

        public BlogEngineUnitOfWork()
        {
            DbContext = new BlogEngineDbContext();
        }
        
        public void Commit()
        {
            DbContext.SaveChanges();
        }

        public IRepository<Model.Blog> Blogs
        {
            get { return new BlogEngineRepository<Blog>(DbContext); }
        }

        public void Dispose()
        {
            DbContext.Dispose();
        }
    }
}

7. Now in our MVC 4 Web Project ‘BlogEngine.Web’ add a Nuget Package named ‘StructureMap’

3

8. Now in Web project, create a folder named Infrastructure and add 2 classes ‘BlogEngineControllerFactory’ and ‘BootStrapper’

4

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using StructureMap;
namespace BlogEngine.Web.Infrastructure
{
    public class BlogEngineControllerFactory:DefaultControllerFactory
    {
        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            return ObjectFactory.GetInstance(controllerType) as IController;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using StructureMap;
using BlogEngine.Data.Contract;
using BlogEngine.Data;
using StructureMap.Configuration.DSL;

namespace BlogEngine.Web.Infrastructure
{
    public class BootStrapper
    {
        public static void ConfigureDependencies()
        {
            ObjectFactory.Initialize(x => x.AddRegistry<ControllerRegistry>());
        }
        public class ControllerRegistry : Registry
        {
            public ControllerRegistry()
            {
                For<IBlogEngineUnitOfWork>().Use<BlogEngineUnitOfWork>();
            }
        }
    }
}

9. Now in Global.asax under Application_Start() add the below code.

ControllerBuilder.Current.SetControllerFactory(new BlogEngineControllerFactory());
BootStrapper.ConfigureDependencies();

10. Now add a HomeController and View. The controller code is given below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BlogEngine.Data.Contract;
using BlogEngine.Model;

namespace BlogEngine.UI.Web.Controllers
{
    public class HomeController : Controller
    {
        private IBlogEngineUnitOfWork UoW = null;

        public HomeController(IBlogEngineUnitOfWork _UoW)
        {
            UoW = _UoW;
        }
        
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Index(Blog blog)
        {
            UoW.Blogs.Add(blog);
            UoW.Commit();
            return RedirectToAction("Index");    
        }

        public ActionResult List()
        {
            return View(UoW.Blogs.GetAll());
        }

    }
}

11. A complete Solution Structure Is Given below.

5

About these ads

One Response to “Design an MVC application Using Enity Framework Repository Pattern, Unit Of Work Pattern and Dependency Injection”

  1. Jason said

    Thanks for sharing your knowledge on the topics discussed. Could you also provide sample code for download. My solution does not seem to be able to retrieve data from the database. I followed the steps above and my projects compiled with out any errors. I also manually created the Blog table in SQL Server 2012 and populated it with some sample data. When I access the /List view page which I have created and used a foreach loop to read the data nothing is shown.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

Join 422 other followers