locked
Use of 'Unit of Work' when using a single generic repository? RRS feed

  • Question

  • User1698386060 posted

    I am currently looking into the repository patterns and read that repository patterns can be implement in 2 way:-

    One repository per entity (non-generic) : This type of implementation involves the use of one repository class for each entity. For example, if you have two entities Order and Customer, each entity will have its own repository.

    and

    Generic repository : A generic repository is the one that can be used for all the entities, in other words it can be either used for Order or Customer or any other entity.

    Then I read about the Unit of Work concept and how it can relieve us from database inconsistencies that can be cause by the first way.

    My confusion is regarding the second way.

    Why would I be needing to use 'Unit of work' when I have created a generic repository?

    Since there is no way for any inconsistency to occur.

    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.

    But since I am going to have a single generic repository then what is the need?

    Wednesday, January 10, 2018 11:40 AM

Answers

  • User753101303 posted

    Yes but the first save could work and the 2nd fail. Now the user have to add back what  is missing if the app allows that.

    If you have a single context, you call save only once. If it works ALL is saved and if it fails, NO change at all is done. Avoiding to save some but not all intended changes is perhaps something you want to avoid.

    Do you have multiple save calls in your app? Can you tolerate an error that would save some changes but would lose other changes ?

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 10, 2018 2:38 PM

All replies

  • User753101303 posted

    Hi,

    Not sure which kind of inconsistency you are taking about. I believe they meant "Generic" as show at https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx while you perhaps understood this as having ever a single repository instance ?

    And so if you can have multiple repositories (even if they use C# generics) you have to ensure they all share the same underlying dbcontext.

    Wednesday, January 10, 2018 12:07 PM
  • User475983607 posted

    A generic repository means the pattern can handle many different types of repositories.  It does not mean there is one repo.  Unit of Work provides connection/context management where a single save will save all repositories as a single unit of work.

    Wednesday, January 10, 2018 12:07 PM
  • User1698386060 posted

    I just want to see what kind of inconsistency can happen if you can site an example!

    Wednesday, January 10, 2018 12:23 PM
  • User1698386060 posted

    Can you just site an example where the inconsistency will take place if say a controller has many repository instances?

    Wednesday, January 10, 2018 12:24 PM
  • User475983607 posted

    Can you just site an example where the inconsistency will take place if say a controller has many repository instances?

    I'm not sure what inconsistencies you're referring to. 

    Wednesday, January 10, 2018 12:32 PM
  • User753101303 posted

    Depends how your code is done. If each repository is using a separate context you'll have to call "Save" against each one and if it fails at some point you'll end up with some changes being saved but not all.

    See how EF works. "Unit of work" is at the DbContext level and the "repository pattern" is at the DbSet level.

    Edit: seems pretty well explained at:

    https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application#implement-a-generic-repository-and-a-unit-of-work-class :

    "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."

    It assume this is the kind of inconsistency you are talking about? For now it seems you are thinking you'll ever use a single repository. It might be true for simple scenarios but you'll likely run into having to use mutliple repositories sooner or later...

    Ah this is waht you follows. So it shows how CourseRepository and DepartementRepository are sharing a single UnitOfWork and so unitOfWork.Save() will save all or nothing.

    It is not uncommon to see repository implementations where each repository have its own underlying context (ie you have multiple "unit of works" rather than a single "unit") which can cause issues.

    Wednesday, January 10, 2018 12:37 PM
  • User1698386060 posted

    "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."



    Won't I get an exception if it has failed?
    Since every controller is surrounded inside by try, catch block.

    Wednesday, January 10, 2018 12:44 PM
  • User475983607 posted

    The Unit of Work pattern solves a common programming problem which is clearly expressed in the linked documentation.  It is up to you to determine if the pattern is appropriate for your project. 

    Won't I get an exception if it has failed?
    Since every controller is surrounded inside by try, catch block.

    It sounds like you have designed a solution that works for your project and you do not need the Unit of Work pattern.  

    Wednesday, January 10, 2018 2:24 PM
  • User753101303 posted

    Yes but the first save could work and the 2nd fail. Now the user have to add back what  is missing if the app allows that.

    If you have a single context, you call save only once. If it works ALL is saved and if it fails, NO change at all is done. Avoiding to save some but not all intended changes is perhaps something you want to avoid.

    Do you have multiple save calls in your app? Can you tolerate an error that would save some changes but would lose other changes ?

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, January 10, 2018 2:38 PM