csharppulse.blogspot.in-learning_mvc_part_6_generic_repository_pattern_in_mvc3_application_with_entity_framework.pdf...

Upload: zoranmatusko

Post on 01-Jun-2018

216 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 1/10

    csharppulse.blogspot.in http://csharppulse.blogspot.in/2013/09/learning-mvc-part-6-generic-repository.html

    Learning MVC Part 6: Generic Repository Pattern in MVC3

    Application with Entity Framework

    Download Complete Source Code

    Introduction

    Creating a Generic Repository pattern in an MVC3 application with Entity Framework is the last topic that we are

    about to cover in our journey of learning MVC.

    The article will focus on Unit of Work Pattern and Repository Pattern, and shows how to perform CRUD operation

    in an MVC application when there could be a possibility of creating more than one repository class. To overcome

    this possibility and overhead, we make a Generic Repository class for all other repositories and implement a Unit

    of Work pattern to provide abstraction.

    Our roadmap towards Learning MVCJust to remind our full roadmap towards learning MVC,

    1. Part1: Introduction to MVCarchitecture and Separation of Concerns.

    2. Part 2: Creating MVC Application fromscratch and connecting it with database using LINQ to SQL.

    3. Part 3: Connecting the MVC Application with the help ofEntityFramework DB-First approach.

    4. Part 4: Connecting the MVC Application with the help of EntityFramework Code-First approach.

    5. Part 5: Implementing Repository Pattern in MVC Application with EntityFramework.

    6. Part 6: Implementing a generic Repository Pattern and Unit Of Work pattern in MVC Application

    with EntityFramework.

    Pre-requisites

    There are few pre-requisites before we start with the article,

    1. We have running sample application that we created in fifthpart of the article series.

    2. We have Entity Framework 4.1 package or DLL on our local file system.

    3. We understand how MVC application is created (follow secondpart of the series).

    Why Generic Repository

    http://www.codeproject.com/Articles/620197/Learning-MVC-Part-2-Creating-MVC-Application-and-Phttp://www.codeproject.com/Articles/631668/Learning-MVC-Part-5-Repository-Pattern-in-MVC3-Apphttp://csharppulse.blogspot.in/2013/09/learning-mvc-part-6-generic-repository.htmlhttp://csharppulse.blogspot.in/2013/08/learning-mvc-part-2-creating-mvc.htmlhttp://csharppulse.blogspot.in/2013/08/learning-mvc-part-1-introduction-to-mvc.htmlhttp://www.codeproject.com/Articles/620197/Learning-MVC-Part-2-Creating-MVC-Application-and-Phttp://www.codeproject.com/Articles/631668/Learning-MVC-Part-5-Repository-Pattern-in-MVC3-Apphttp://csharppulse.blogspot.in/2013/09/learning-mvc-part-6-generic-repository.htmlhttp://csharppulse.blogspot.in/2013/09/learning-mvc-part-5repository-pattern.htmlhttp://csharppulse.blogspot.in/2013/09/learning-mvc-part-4-creating-mvc.htmlhttp://csharppulse.blogspot.in/2013/08/learning-mvc-part-3-creating-mvc.htmlhttp://csharppulse.blogspot.in/2013/08/learning-mvc-part-2-creating-mvc.htmlhttp://csharppulse.blogspot.in/2013/08/learning-mvc-part-1-introduction-to-mvc.htmlhttps://docs.google.com/file/d/0B6aCOfU3iep1c1laaWtTZWNaQnM/edit?usp=sharinghttp://csharppulse.blogspot.in/2013/09/learning-mvc-part-6-generic-repository.htmlhttp://csharppulse.blogspot.in/
  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 2/10

    We have already discussed what Repository Pattern is and why do we need Repository Pattern in our lastarticle.

    We created a User Repository for performing CRUD operations, but think of the scenario where we need 10 such

    repositories.

    Are we going to create these classes? Not good, it results in a lot of redundant code. So to overcome this

    situation well create a Generic Repository class that will be called by a property to create a new repository thus

    we do not result in lot of classes and also escape redundant code too. Moreover we save a lot of time that could

    be wasted creating those classes.

    Unit of Work Pattern

    According to Martin Fowler 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."

    From MSDN, The Unit of Work pattern isn't necessarily something that you will explicitly build yourself, but the

    pattern shows up in almost every persistence tool. The ITransactioninterface in NHibernate, the

    DataContextclass in LINQ to SQL, and the ObjectContextclass in the Entity Framework are all examples of

    a Unit of Work. For that matter, the venerable DataSet can be used as a Unit of Work.

    Other times, you may want to write your own application-specific Unit of Work interface or class that wraps the

    inner Unit of Work from your persistence tool. You may do this for a number of reasons. You might want to add

    application-specific logging, tracing, or error handling to transaction management. Perhaps you want to

    encapsulate the specifics of your persistence tooling from the rest of the application. You might want this extraencapsulation to make it easier to swap out persistence technologies later. Or you might want to promote

    testability in your system. Many of the built-in Unit of Work implementations from common persistence tools are

    difficult to deal with in automated unit testing scenarios."

    The Unit of Work class can have methods to mark entities as modified, newly created, or deleted. The Unit of

    Work will also have methods to commit or roll back all of the changes as well.

    The important responsibilities of Unit of Work are,

    To manage transactions.

    To order the database inserts, deletes, and updates.

    To prevent duplicate updates. Inside a single usage of a Unit of Work object, different parts of the code may

    mark the same Invoice object as changed, but the Unit of Work class will only issue a single UPDATE

    command to the database.

    The value of using a Unit of Work pattern is to free the rest of our code from these concerns so that you can

    otherwise concentrate on business logic.

    Why use Unit of Work?

    Again Martin Fowler statements, "When you're pulling data in and out of a database, it's important to keep track of

    what you've changed; otherwise, that data won't be written back into the database. Similarly you have to insert

    new objects you create and remove any objects you delete.

    You can change the database with each change to your object model, but this can lead to lots of very small

    database calls, which ends up being very slow. Furthermore it requires you to have a transaction open for the

    whole interaction, which is impractical if you have a business transaction that spans multiple requests. The

    http://www.codeproject.com/Articles/631668/Learning-MVC-Part-5-Repository-Pattern-in-MVC3-App
  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 3/10

    situation is even worse if you need to keep track of the objects you've read so you can avoid inconsistent reads.

    A Unit of Work keeps track and takes responsibility of everything you do during a business transaction that can

    affect the database. When you're done, it figures out everything that needs to be done to alter the database as a

    result of your work."

    You see I dont have to concentrate much on theory, we already have great definitions existing, all we needed is

    to stack them in a correct format.

    Using the Unit of Work

    One of the best ways to use the Unit of Work pattern is to allow disparate classes and services to take part in a

    single logical transaction. The key point here is that you want the disparate classes and services to remain

    ignorant of each other while being able to enlist in a single transaction. Traditionally, you've been able to do this b

    using transaction coordinators like MTS/COM+ or the newer System.Transactions namespace. Personally, I prefe

    using the Unit of Work pattern to allow unrelated classes and services to take part in a logical transaction because

    I think it makes the code more explicit, easier to understand, and simpler to unit test(From MSDN).

    Creating a Generic Repository

    Cut the Redundancy

    Step 1: Open up our existing MVC3 application created in Part5in Visual Studio.

    Step2: Right click Learning MVC project folder and create a folder named GenericRepositoryand add a class

    namedGenericRepository.csto that folder.

    The code of the GenericRepository.csclass is as follows:

    http://www.codeproject.com/Articles/631668/Learning-MVC-Part-5-Repository-Pattern-in-MVC3-App
  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 4/10

    using System;

    using System.Collections.Generic;

    using System.Data;

    using System.Data.Entity;

    using System.Linq;

    using System.Linq.Expressions;

    namespace LearningMVC.GenericRepository

    { public class GenericRepository where TEntity : class

    {

    internal MVCEntities context;

    internal DbSet dbSet;

    public GenericRepository(MVCEntities context)

    {

    this.context = context;

    this.dbSet = context.Set();

    }

    public virtual IEnumerable Get()

    {

    IQueryable query = dbSet;

    return query.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;

    }

    }

    }

  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 5/10

    We can see, we have created the generic methods and the class as well is generic, when instantiating this class

    we can pass any model on which the class will work as a repository and serve the purpose.

    TEntityis any model/domain/entity class. MVCEntitiesis our DBContextas discussed in earlier parts.

    Step 3: Implementing UnitOfWork: Create a folder named UnitOfWorkunder LearningMVC project, and add a

    class UnitOfWork.csto that folder.

    The code of the class is as follows:

    using System;

    using LearningMVC.GenericRepository;

    namespace LearningMVC.UnitOfWork

    {

    public class UnitOfWork : IDisposable

    {

    private MVCEntities context = new MVCEntities();

    private GenericRepository userRepository;

    public GenericRepository UserRepository {

    get

    {

    if (this.userRepository == null)

    this.userRepository = new GenericRepository

    (context);

    return userRepository;

    }

    }

    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);

    }

    }

    }

    We see the class implements IDisposableinterface for objects of this class to be disposed.

    We create object of DBContextin this class, note that earlier it was used to be passed in Repository class from

  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 6/10

    a controller.

    Now it's time to create our User Repository. We see in the code itself that, simply a variable named

    userRepositoryis declared as private GenericRepository userRepository;of type

    GenericRepositoryserving User entity to TEntitytemplate.

    Then a property is created for the same userRepositoryvariable in a very simplified manner,

    public GenericRepository UserRepository

    { get

    {

    if (this.userRepository == null)

    this.userRepository = new GenericRepository

    (context);

    return userRepository;

    }

    }

    I.e., mere 6-7 lines of code. Guess what? Our UserRepository is created.

    (Taken from Google)

    You see it was as simple as that, you can create as many repositories you want by just creating simple properties,

    and no need to create separate classes. And now you can complete the rest of the story by yourself,

    confused???? Yes it'sDBOperations, let's do it.

    Step 4: In MyController, declare a variable unitOfWorkas:

    private UnitOfWork.UnitOfWork unitOfWork = new

    UnitOfWork.UnitOfWork();

    Now this unitOfWork instance of UnitOfWork class holds all th repository properties,if we press ." After it, it will

    show the repositories.So we can choose any of the repositories created and perform CRUD operations on them.

    E.g. our Index action:

  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 7/10

    public ActionResult Index()

    {

    var userList = from user in unitOfWork.UserRepository.Get() select user;

    var users = new List();

    if (userList.Any())

    {

    foreach (var user in userList)

    {

    users.Add(new LearningMVC.Models.UserList() { UserId = user.UserId,Address = user.Address, Company = user.Company,

    FirstName = user.FirstName, LastName = user.LastName,

    Designation = user.Designation, EMail = user.EMail, PhoneNo =

    user.PhoneNo });

    }

    }

    ViewBag.FirstName = "My First Name";

    ViewData["FirstName"] = "My First Name";

    if(TempData.Any())

    {

    var tempData = TempData["TempData Name"]; }

    return View(users);

    }

    Here,

    unitOfWork.UserRepository> Accessing UserRepository.

    unitOfWork.UserRepository.Get()-> Accessing Generic Get()method to get all users.

    Earlier we used to have MyControllerconstructor like:

    public MyController()

    {

    this.userRepository = new UserRepository(new

    MVCEntities());

    }

    Now, no need to write that constructor, in fact you can remove the UserRepositoryclass and Interface we

    created in part 5 of Learning MVC.

    I hope you can write the Actions for rest of the CRUD operations as well.

    Details

  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 8/10

    public ActionResult Details(int id)

    {

    var userDetails =

    unitOfWork.UserRepository.GetByID(id);

    var user = new LearningMVC.Models.UserList();

    if (userDetails != null)

    {

    user.UserId = userDetails.UserId;

    user.FirstName = userDetails.FirstName; user.LastName = userDetails.LastName;

    user.Address = userDetails.Address;

    user.PhoneNo = userDetails.PhoneNo;

    user.EMail = userDetails.EMail;

    user.Company = userDetails.Company;

    user.Designation = userDetails.Designation;

    }

    return View(user);

    }

    Create:

    [HttpPost]

    public ActionResult Create(LearningMVC.Models.UserList userDetails)

    {

    try

    {

    var user = new User();

    if (userDetails != null)

    {

    user.UserId = userDetails.UserId;

    user.FirstName = userDetails.FirstName;

    user.LastName = userDetails.LastName;

    user.Address = userDetails.Address;

    user.PhoneNo = userDetails.PhoneNo;

    user.EMail = userDetails.EMail;

    user.Company = userDetails.Company;

    user.Designation = userDetails.Designation;

    }

    unitOfWork.UserRepository.Insert(user);

    unitOfWork.Save();

    return RedirectToAction("Index"); }

    catch

    {

    return View();

    }

    }

    Edit:

  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfra 9/10

  • 8/9/2019 csharppulse.blogspot.in-Learning_MVC_Part_6_Generic_Repository_Pattern_in_MVC3_Application_with_Entity_Framew

    http:///reader/full/csharppulseblogspotin-learningmvcpart6genericrepositorypatterninmvc3applicationwithentityfr 10/10

    public ActionResult Delete(int id)

    {

    var user = new LearningMVC.Models.UserList();

    var userDetails = unitOfWork.UserRepository.GetByID(id);

    if (userDetails != null)

    {

    user.FirstName = userDetails.FirstName;

    user.LastName = userDetails.LastName; user.Address = userDetails.Address;

    user.PhoneNo = userDetails.PhoneNo;

    user.EMail = userDetails.EMail;

    user.Company = userDetails.Company;

    user.Designation = userDetails.Designation;

    }

    return View(user);

    }

    [HttpPost]

    public ActionResult Delete(int id, LearningMVC.Models.UserList userDetails){

    try

    {

    var user = unitOfWork.UserRepository.GetByID(id);

    if (user != null)

    {

    unitOfWork.UserRepository.Delete(id);

    unitOfWork.Save();

    }

    return RedirectToAction("Index");

    }

    catch

    {

    return View();

    }

    }

    Note: Images are taken from Google images.

    Conclusion

    We now know how to make generic repositories too, and perform CRUD operations using it.

    We have also learnt UnitOfWork pattern in detail. Now you are qualified and confident enough to apply these

    concepts in your enterprise applications. This was the last part of this MVC series, let me know if you feel to

    discuss any topic in particular or we can also start any other series as well. For more informative articles,visit my

    blogA Practical Approach.

    Happy coding :-).

    http://csharppulse.blogspot.in/