locked
Is really Repository pattern and Unit Of Work needed ? RRS feed

  • Question

  • User1693415052 posted

    Am developing an application in MVC 5. I just wanted to know why Repository pattern and UOW is implemented. Is there any benefit in implementing them ?

    1. I googled and found that this Repo and UOW is useful in unit testing. If am not unit testing my application, then also this pattern is needed ??
    2. By implementing this pattern will there be any rise in performance ?

    Any king suggestion will be highly appreciated . Also please guide me a link where i can learn this pattern . 

    Friday, December 19, 2014 12:07 AM

All replies

  • User831885415 posted

    entity framework is not providing full abstraction of data access.

    in future it should not be matter that which database (sql,oracle, xml) you use.

    it is possible if you implement a generic data access abstraction using repository pattern and unit of work

    Friday, December 19, 2014 12:44 AM
  • User1693415052 posted

    Thanks for post. Can you pls suggest some references for Generic repository and Unit of work for Database first approach using EF

    Friday, December 19, 2014 1:45 AM
  • User1693415052 posted

    Thanks for kind reply

    Friday, December 19, 2014 5:52 AM
  • User-821857111 posted

    mdsadullah718

    I just wanted to know why Repository pattern and UOW is implemented. Is there any benefit in implementing them ?

    More often than not, the answer is no - there is no benefit to be had from implementing Repository or Unit Of Work patterns when using Entity Framework. Entity framework already implements these patterns.

    See this: http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/advanced-entity-framework-scenarios-for-an-mvc-web-application#repo

    Friday, December 19, 2014 6:09 AM
  • User-821857111 posted

    entity framework is not providing full abstraction of data access.
    I don't understand what you mean by that, As far as I am concerned, it does.

    Friday, December 19, 2014 6:16 AM
  • User1196679051 posted

    Mikesdotnetting

    More often than not, the answer is no - there is no benefit to be had from implementing Repository or Unit Of Work patterns when using Entity Framework. Entity framework already implements these patterns.

    Do you write Entity Framework queries in services in BLL? Writing unit test for these services mu be awful. For me it is a bad practise - methods in these services with Entity Framework queries must be very long, what is more in that case you must use DBContext in services to write there Entity Framework queries - it isn't a good solution for me. I write Entity Framework queries in my repositories in DAL and I use my repositories in services in BLL - maybe it is over-abstraction but my services are short and easy to write unit tests and I don't use DbContext in BLL.

    Monday, December 22, 2014 3:09 AM
  • User-821857111 posted

    Do you write Entity Framework queries in services in BLL? Writing unit test for these services mu be awful.

    The OP said that they are not unit testing.

    Monday, December 22, 2014 3:18 AM
  • User1693415052 posted

    @Mikes thanks for you comment. i didn't say that am not unit testing my application. Am just asking "IF AM NOT UNIT TESTING THEN ALSO IS THESE PATTERN NEEDED" ?  Actually what my questions is, is repo and UOW is purely intended for unit testing ? or its implemented for some other purpose ? According to Tom Dykstra

    "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 and can facilitate automated unit testing or test-driven development (TDD)."  

    Monday, December 22, 2014 3:42 AM
  • User1196679051 posted

    For me if you use unit of work and repository, your application is easier to develop (because all queries you have in DAL and business logic in BLL) and easier to write unit test and more secure because in BLL you don't have access to DbContext.

    Monday, December 22, 2014 3:53 AM
  • User1693415052 posted

    @alexandrr

     Thanks for comment .

     I'd like to hear mikesdotnetting's suggestion too !!!

    Monday, December 22, 2014 3:57 AM
  • User-821857111 posted

    i didn't say that am not unit testing my application. Am just asking "IF AM NOT UNIT TESTING THEN ALSO IS THESE PATTERN NEEDED" ?

    I kind of assumed you meant that you weren't unit testing, but it doesn't matter if you are or not, for the purposes of your question. 

    "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.
    That's generally true. However, EF DbSets are already an implementation of the Repository pattern, and DbContext is an implementation of the Unit Of Work. More and more and more people are questioning the value of writing a "Repository wrapper" class around a repository pattern. You add a class called ProductRepository and then put a method in it called FindById which wraps the DbSet<T>.Find() method. How is that an implementation of the repository pattern? 

    To my mind, there is nothing wrong with having DbContext in your BLL layer. You can mock it in your tests: http://msdn.microsoft.com/en-gb/data/dn314429.aspx



    Monday, December 22, 2014 4:25 AM
  • User1693415052 posted

    Thanks mike. Very much thanks . Now am able to understand do i need to implement or not. 

    Monday, December 22, 2014 6:29 AM
  • User1693415052 posted

    @Mikes,

     After reading your comments, i googled more for Repo and UOW to dive in deep and found an article in MSDN which says , 

    In many applications, the business logic accesses data from data stores such as databases, SharePoint lists, or Web services. Directly accessing the data can result in the following:
    
    Duplicated code
    A higher potential for programming errors
    Weak typing of the business data
    Difficulty in centralizing data-related policies such as caching
    An inability to easily test the business logic in isolation from external dependencies
    Objectives
    
    Use the Repository pattern to achieve one or more of the following objectives:
    
    You want to maximize the amount of code that can be tested with automation and to isolate the data layer to support unit testing.
    You access the data source from many locations and want to apply centrally managed, consistent access rules and logic.
    You want to implement and centralize a caching strategy for the data source.
    You want to improve the code's maintainability and readability by separating business logic from data or service access logic.
    You want to use business entities that are strongly typed so that you can identify problems at compile time instead of at run time.
    You want to associate a behavior with the related data. For example, you want to calculate fields or enforce complex relationships or business rules between the data elements within an entity.
    You want to apply a domain model to simplify complex business logic.

    Complete topic in msdn.microsoft.com/en-us/library/ff649690.aspx

     A repository separates the business logic from the interactions with the underlying data source or Web service. The separation between the data and business tiers has three benefits:
    
    It centralizes the data logic or Web service access logic.
    It provides a substitution point for the unit tests.
    It provides a flexible architecture that can be adapted as the overall design of the application evolves.

    What's your opinion from these article ?  As you have expressed your opinion that  there is nothing wrong with having DbContext in your BLL layer. But this MSDN article is saying that separating Dbcontext from BLL is right way !!  Am expecting your opinion on this . Thanks 

    Monday, December 22, 2014 7:58 AM
  • User1196679051 posted

    In my opinion the best solution is to put all Entity Framework queries in repositories - the code is then easier to read and develop (methods in services are shorter). Also it is easier to share the same complex queries between services because you have got them in repositories.

    Monday, December 22, 2014 8:35 AM
  • User-821857111 posted

    But this MSDN article is saying that separating Dbcontext from BLL is right way

    No it doesn't. It says that you shouldn't directly access data from a database in your BLL. That means you shouldn't have connection strings, SqlClient code and ADO.NET DataReaders and DataSets in your BLL. A DbContext is a Unit Of Work. A DbSet is a Repository. You can have Unit of Work and Repositories in your BLL. Therefore you can have DbContext in your BLL.

    Monday, December 22, 2014 8:40 AM
  • User-1611549905 posted

    In my opinion the best solution is to put all Entity Framework queries in repositories - the code is then easier to read and develop (methods in services are shorter). Also it is easier to share the same complex queries between services because you have got them in repositories.

    Actually, queries are a business concern. They contain business logic, and so they need to be tested as if they were business logic.

    Also, acting as a container for your queries is outside the scope of the Repository pattern. The characteristic feature of a Repository is that it gives you a collection-like interface to your entities. Putting your queries into your Repository is a violation of the Single Responsibility Principle (a class should have one, and only one, reason to change).

    The best way to deal with complex queries is with the Query Object pattern -- one class for each query, with properties that can be set to handle paging, sorting, filtering, prefetch paths, and so on. Simpler queries can be implemented as extension methods on DbSet<T> or IQueryable<T>.

    Monday, December 22, 2014 8:48 AM
  • User-821857111 posted

    In my opinion the best solution is to put all Entity Framework queries in repositorie

    But the DbSet is already a Repository. Take the following code:

    public class StudentRepository : IStudentRepository
    {
        private SchoolContext context;
        public StudentRepository(SchoolContext context)
        {
            this.context = context;
        }
    
        public IEnumerable<Student> GetStudents()
        {
            return context.Students.ToList();
        }
    }

    That's typically what people talk about when they refer to "Repositories" in relation to EF. But the StudentRepository class isn't an implementation of the repository pattern despite its name. It's not even close to a repository. It's a (rather pointless) facade.

    Monday, December 22, 2014 8:49 AM
  • User1196679051 posted

    Yes, I mean that class like StudentRepository in Your example. And if I have more complex query which I want to use in two services, for example in StudentService and TeacherService I can put it in one class - StudentRepository and use that class in two services.

      public IEnumerable<Student> GetStudents()
        {
            return context.Students.Include(x => x.Something).Where(x => x.Something == "...").OrderBy(x => x.Something).ToList();
        }

    Should we duplicate above query in StudentService and TeacherService if we don't use classes like StudentRepository and we need the same query in two services?

    Monday, December 22, 2014 9:08 AM
  • User1196679051 posted

    @Mikes - could you answer? Because it is interesting.

    Monday, December 22, 2014 9:46 AM
  • User-821857111 posted

    Should we duplicate above query in StudentService and TeacherService

    No. You can put it into StudentService once. Then you can call the StudentService.GetStudents() method wherever it needs to be called.

    Monday, December 22, 2014 10:07 AM
  • User1693415052 posted

    In my opinion the best solution is to put all Entity Framework queries in repositories - the code is then easier to read and develop (methods in services are shorter). Also it is easier to share the same complex queries between services because you have got them in repositories.

    @alexandrr , i agree with your point, but i think we can have Entity Framework queries in repositories  only if we have one repository per entity. What if am using a generic repository ? That is only one repository for all entities. In that case how we can have all our Entity Framework queries in repositories ? 

    Monday, December 22, 2014 11:50 PM
  • User1196679051 posted

    I always use repository per entity. Each repository inherit from a base class which has got common methods like: GetById, GetAll, Insert, Update, Delete.

    Tuesday, December 23, 2014 2:21 AM
  • User1693415052 posted

    Ya, am able to get you. But am using generic repository and a generic base class(Interface)for all entities. In that case how to write EF queries in Repo ? Have you any idea ? I too has common methods like  GetById, GetAll, Insert, Update, Delete in my base class. Except these methods, if we need some other method then how to use them in Repo ?  Any idea is welcome !!

    Tuesday, December 23, 2014 3:22 AM
  • User1196679051 posted

    The generic repository for all entities in't a good approach because you can only use common queries from the generic repository class. In that case Mikes approach with DbContext and queries in services is better.

    I create repository per entity and place there my custom queries, then I use that repository / repositories in service. And in my class called UnitOfWork I have method Save() with code _context.SaveChanges(). I use this class also in services if I need to commit changes.

    Tuesday, December 23, 2014 3:39 AM
  • User1693415052 posted

    Is your approach suitable for entities > 200 ? I have more than 200 tables in my Database . Creating a repo per entity is a tedious task . isn't it ??? Is there any T4 template to create repo per entity ?? 

    Tuesday, December 23, 2014 6:58 AM
  • User1196679051 posted

    I don't create repository per EACH table. For important tables like: Customers, Orders, Products I create repositories of course but some of mine repositories don't refer to concrete table.

    Tuesday, December 23, 2014 7:17 AM
  • User1693415052 posted

    I was discussing regarding unit testing using repo pattern with my friend. He asked me a question , if we use repo pattern for unit testing, then actual DB will not be affected. That is we will pass dummy data for testing. Then how we will test if the DB is working correctly ? If we have constraints(Primary key,Not null, Check etc) in our database table then that will not be tested . Also we cant test the data access speed of DB ? Also if use stored procedure and views then that will not be tested !! Any solution there ???

    Tuesday, December 30, 2014 8:07 AM
  • User-1611549905 posted

    This is actually a valid point. The fact of the matter is that the interaction between your DAL and your database is one of the most complex, business critical and error-prone parts of your entire application. You do need to test against an actual test database, which should be reconstructed from a known baseline using the same set of change scripts as you use on your production database.

    The so-called "best practice" advocated by some, that your tests should never hit a database but should only use mock data, is, IMO, a recipe for disaster.

    Tuesday, December 30, 2014 8:18 AM
  • User-821857111 posted

    mdsadullah718

    f we use repo pattern for unit testing, then actual DB will not be affected. That is we will pass dummy data for testing. Then how we will test if the DB is working correctly ?

    You should not involve the database at all in unit tests. When you include the database, it is not a unit test. It's an integration test.

    Tuesday, December 30, 2014 8:20 AM
  • User-821857111 posted

    The so-called "best practice" advocated by some, that your tests should never hit a database

    Unit tests should not hit the database. They should only really test units of business logic. Of course it's important to ensure that the database is working correctly and that the right data is being returned. But you don't use unit tests for that. 

    Tuesday, December 30, 2014 8:23 AM
  • User-1611549905 posted

    Unit tests should not hit the database. They should only really test units of business logic. Of course it's important to ensure that the database is working correctly and that the right data is being returned. But you don't use unit tests for that.

    Yes, I know that. But the problem with saying "unit tests should not hit the database" is that far too many people misunderstand that to mean "tests in general should not hit the database."

    It really needs to be re-phrased in a way that isn't open to that kind of misunderstanding.

    Tuesday, December 30, 2014 8:54 AM
  • User-821857111 posted

    "unit tests should not hit the database"

    That's unambiguous enough for me.

    Tuesday, December 30, 2014 2:56 PM
  • User-1611549905 posted

    It's unambiguous enough for me too, but I have had to deal with people for whom it isn't.

    For example, there was one occasion when I had to set up a Continuous Integration server -- when I said I needed a test database for it to run the integration tests, one person told me that I wasn't sticking to best practices because "your tests shouldn't hit the database." No discussion of integration tests versus unit tests or anything.

    And integration tests that hit the database are important, because otherwise you are failing to test functionality that is both business critical and error-prone.

    Tuesday, December 30, 2014 3:33 PM
  • User1693415052 posted

    @Mikes, 

    Coming to your point, Lets say Unit testing is only for testing Unit blocks for application not the database. So we have to make two tests 
    1. Unit Test
    2. Integration Test
    But doing multiple tests requires more time and cost too .  Should we do two these two tests individually ??

    Any other way to test both business logic(Unit test) and Database test(Integration test) in a single test ??

    Tuesday, December 30, 2014 11:40 PM
  • User-821857111 posted

    There are a lot of levels of test that need to be performed with regard to software development: http://en.wikipedia.org/wiki/Software_testing#Testing_levels

    Any other way to test both business logic(Unit test) and Database test(Integration test) in a single test ??

    No. They must be done individually. A test should have only one reason for failure. Otherwise when a test fails, you find yourself debugging the test to see what actually failed. 

    Testing is an upfront investment in time and cost. The pay off is in less bugs and a system that easier (and therefore cheaper) to maintain. 

    Wednesday, December 31, 2014 4:29 AM