Basic Generic Repository Pattern and Unity of FrameWork in ASP.NET MVC3: Part 2

Description

In my previous article w
e went through the basics of repository patterns with the implementation of an Interface.

In this article I will define for you a simple "Blog post" application with ASP.Net MVC3 using an actual generic repository pattern with the unity of work pattern.

Now what are Generic Repository and Unit of Work Class?

Creation of a repository class for each entity type could result in a lot of redundant code, and it could result in partial updates between model classes.
For example, suppose in a single transaction we have to update two different entity types.

Now if each uses a separate database context instance, then 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.

According to Martin Fowler, the Unit of Work pattern "maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. That means to resolve the database consistency issue.

Now in this article I will develop a small "Blog-Comment" application with MVC3 using a Generic Repository.

We have 2 model classes with 1 to many relationships.

Step 1:

Now in our "BlogProject" MVC3 project we have to first add 3 new projects with in the Solution Explorer.

  1. DAL
  2. REPOSITORY
  3. UnityFramework

MVC1.gif

Step 2:


Now Under Model Folder we have to create our 2 model classes (Blog and Comments).

public class Blog
{
    [Key]
    public int BlogID { get; set; }

    [Required(ErrorMessage = "Title is required.")]

    [Display(Name = "Title Name")]
    [MaxLength(100)]
    public string Title { get; set; }

    [Required(ErrorMessage = "Author Name is required.")]

    [Display(Name = "AuthorName")]
    [MaxLength(50)]
    public string AuthorName { get; set; }

    [Required(ErrorMessage = "Description is required.")]

    [Display(Name = "Description")]
    [MaxLength(1000)]
    public string Description { get; set; }

    [Required(ErrorMessage = "Publish date is required.")]

    [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
    [Display(Name = "Publish Date")]
    public DateTime? PublishDate { get; set; }
 
    public virtual ICollection<Comment> Comment { get; set; }
}
 
public class Comment
{
    [Key]
    public int CommentId { get; set; }
    public string Comments { get; set; }

    public int BlogID { get; set; }
    public virtual Blog Blogs { get; set; }
}

Step 3:

Now create a new class named "BlogDbContext.cs" under the "DAL" folder.

This will be our Entity Framework class.

public class BlogDbContext:DbContext
{
    public DbSet<Blog> Blog { get; set; }
    public DbSet<Comment> Comment { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();           

    }

Step 4:

Now under Our "Repository" folder create the "GenericRepository.cs" class.

In this class we will write our generic method for dealing our entity class with our repository classes (blog, comment). See the following picture:

MVC2.gif

Here is the actual code:

    public class GenericRepository<TEntity> where TEntity : class
    {
        internal BlogDbContext context;
        internal DbSet<TEntity> dbSet;

        public GenericRepository(BlogDbContext context)
        {
            this.context = context;
            this.dbSet = context.Set<TEntity>();
        }
        public IEnumerable<TEntity> GetData()
        {
            return dbSet.ToList ();
        }

        public virtual TEntity GetByID(object id)
        {
            return dbSet.Find(id);
        }
 
        public virtual void Insert(TEntity entity)
        {
            dbSet.Add(entity);
        }

        public virtual void Delete(object id)
        {
            TEntity entityToDelete = dbSet.Find(id);
            Delete(entityToDelete);
        }

        public virtual void Delete(TEntity entityToDelete)
        {
            if (context.Entry(entityToDelete).State == EntityState.Detached)
            {
                dbSet.Attach(entityToDelete);
            }
            dbSet.Remove(entityToDelete);
        }
 
        public virtual void Update(TEntity entityToUpdate)
        {
            dbSet.Attach(entityToUpdate);
            context.Entry(entityToUpdate).State = EntityState.Modified;
        }
    }


Step 5:

Now it's the time for implementing the "Unity of Work" pattern.

A Unity of work class shares a single database context and serves one purpose; to make sure that when we use multiple repositories.

That way, when a unit of work is complete you can call the SaveChanges method on that instance of the context and be assured that all related changes will be done successfully. [maintain] Now Under "UnityFramwork" project create a class named "UnituOfWork.cs".

public class UnituOfWork:IDisposable
{
    private GenericRepository<Blog> BlogRepository;
    private GenericRepository<Comment> CommentRepository;
    BlogDbContext context = new BlogDbContext();

    #region RepositoryClasses
    public GenericRepository<Blog> blogRepository
    {
        get
        {
            if (this.BlogRepository == null)
                this.BlogRepository = new GenericRepository<Blog>(context);
            return BlogRepository;
        }
    }
 
    public GenericRepository<Comment> commentRepository
    {
        get
        {
            if (this.CommentRepository == null)
                this.CommentRepository = new GenericRepository<Comment>(context);
            return CommentRepository;
        }
    }

    #endregion

    public void Save()
    {
        context.SaveChanges();
    }
    private bool disposed = false;
    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        this.disposed = true;
    }
 
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}


MVC3.gif
The code creates class variables for the database context and each repository. For the context variable, a new context is instantiated.

Now see this piece of code:

MVC4.gif

Each repository property checks whether the repository already exists. If not, it instantiates the repository, passing in the context instance.

As a result, all repositories share the same context instance.

The Save method calls SaveChanges on the database context on last.

Step 6:

Now in the MVC3 blog project under controller folder create a new controller class named "BlogController" and paste the following code:

public class BlogController : Controller
{
    private UnituOfWork unitOfWork = new UnituOfWork();
    //
    
// GET: /Blog/

    public ActionResult Index()
    {
          
        
//var courses = unitOfWork.blogRepository.Get(includeProperties: "Blog");

        var courses = unitOfWork.blogRepository.GetData();
        return View(courses);
    }

    public ActionResult Create()
    {
        // PopulateDepartmentsDropDownList();
        return View();
    }

    [HttpPost]
    public ActionResult Create(Comment Comment)
    {
        try
        {
            if (ModelState.IsValid)
            {
                unitOfWork.commentRepository.Insert(Comment);
                unitOfWork.Save();
                return RedirectToAction("Index");
            }
        }
        catch (DataException)
        {
            //Log the error (add a variable name after DataException)
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
        }
        //PopulateDepartmentsDropDownList(course.DepartmentID);
        return View(Comment);
    }

    public ActionResult Edit(int id)
    {
        Comment Comment = unitOfWork.commentRepository.GetByID(id);

        return View(Comment);
    }

    [HttpPost]
    public ActionResult Edit(Comment Comment)
    {
        try
        {
            if (ModelState.IsValid)
            {
                unitOfWork.commentRepository.Update(Comment);
                unitOfWork.Save();
                return RedirectToAction("Index");
            }
        }
        catch (DataException)
        {
            //Log the error (add a variable name after DataException)
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
        }
        //PopulateDepartmentsDropDownList(course.DepartmentID);
        return View(Comment);
    }
}


This code adds a class variable for the UnitOfWork class. (If we were using interfaces here, you wouldn't initialize the variable here; instead, you'd implement a pattern of two constructors.)

private UnitOfWork unitOfWork = new UnitOfWork();

In the rest of the class, all references to the database context are replaced by references to the appropriate repository, using UnitOfWork properties to access the repository.

The Dispose method disposes the UnitOfWork instance.

Comment Comment = unitOfWork.CourseRepository.GetByID(id);
// ...
unitOfWork.CourseRepository.Insert(Comment);
unitOfWork.Save();
// ...
Comment Comment= unitOfWork.CourseRepository.GetByID(id);
// ...
unitOfWork.CourseRepository.Update(Comment);
unitOfWork.Save();
// ...
Comment Comment = unitOfWork.CourseRepository.GetByID(id);
// ...
unitOfWork.CourseRepository.Delete(id);
unitOfWork.Save();
// ...
unitOfWork.Dispose();

Now form the controller class creates the required "Razore" view.

Conclusion

So in this article we have learned how to implement an actual generic repository pattern with a unity of work pattern class with Entity Framework.


Similar Articles