Do we need to use the Repository pattern when working in ASP.NET MVC with ORM solutions?

前端 未结 3 1520
刺人心
刺人心 2021-01-30 03:43

I am bit curious as to what experience other developers have of applying the Repository pattern when programming in ASP.NET MVC with Entity Framework or NHibernate. It seems to

相关标签:
3条回答
  • 2021-01-30 03:55

    The answer is no if you do not need to be able to switch ORM or be able to test any class that has a dependency to your ORM/database.

    If you want to be able to switch ORM or be able to easily test your classes which uses the database layer: Yes you need a repository (with an interface specification).

    You can also switch to a memory repository (which I do in my unit tests), a XML file or whatever if you use repository pattern.

    Update

    The problem with most repository pattern implementations which you can find by Googling is that they don't work very well in production. They lack options to limit the result (paging) and ordering the result which is kind of amazing.

    Repository pattern comes to it's glory when it's combined with a UnitOfWork implementation and has support for the Specification pattern.

    If you find one having all of that, let me know :) (I do have my own, exception for a well working specification part)

    Update 2

    Repository is so much more than just accessing the database in a abstracted way such as can be done by ORM's. A normal Repository implementation should handle all aggregate entities (for instance Order and OrderLine). Bu handling them in the same repository class you can always make sure that those are built correctly.

    But hey you say: That's done automatically for me by the ORM. Well, yes and no. If you create a website, you most likely want to edit only one order line. Do you fetch the complete order, loop through it to find the order, and then add it to the view?

    By doing so you introduce logic to your controller that do not belong there. How do you do it when a webservice want's the same thing? Duplicate your code?

    By using a ORM it's quite easy to fetch any entity from anywhere myOrm.Fetch<User>(user => user.Id == 1) modify it and then save it. This can be quite handy, but also add code smells since you duplicate code and have no control over how the objects are created, if they got a valid state or correct associations.

    The next thing that comes to mind is that you might want to be able to subscribe on events like Created, Updated and Deleted in a centralized way. That's easy if you have a repository.

    For me an ORM provides a way to map classes to tables and nothing more. I still like to wrap them in repositories to have control over them and get a single point of modification.

    0 讨论(0)
  • 2021-01-30 04:00

    I think it make sense only if you want to decrease level of dependency. In the abstract you can have IPostRepository in your infrastructure package and several independent implementations of this interface built on top of EF or NH, or something else. It useful for TDD.

    In practice NH session (and EF context) implements something like the "Unit of Work" pattern. Furthermore with NH and the Repository pattern you can get a lot of bugs and architectural issues.

    For example, NH entity can be saved bypassing your Repository implementation. You can get it from session (Repository.Load), change one of its properties, and call session.Flush (at the end of request for example, because Repository pattern doesn't suppose flushing) - and your changes will be successfully processed in db.

    0 讨论(0)
  • 2021-01-30 04:10

    You've only mentioned basic CRUD actions. Doing these directly does mean you have to be aware of transactions, flushing and other things that a repository can wrap up, but I guess the value of repositories becomes more apparent when you think about complex retrieval queries.

    Imagine then that you do decide to use the NHibernate session directly in your application layer.

    You will need to do the equivalent of WHERE clauses and ORDER BYs etc, using either HQL or NHibernate criteria. This means your code has to reference NHibernate, and contains ideas specific to NHibernate. This makes your application hard to test and harder for others unfamiliar with NH to follow. A call to repository.GetCompletedOrders is much more descriptive and reusable than one that includes something like "where IsComplete = true and IsDeleted = false..." etc.

    You could use Linq to NHibernate instead, but now you have the situation where you can easily forget that you're working on an IQueryable. You could end up chaining Linq expressions which generate enormous queries when they execute, without realising it (I speak from experience)! Mike Hadlow sparked a conversation on essentially this topic in his post Should my repository expose IQueryable.

    N.b. If you don't like having lots of methods on custom repositories for different queries (like GetCompletedOrders), you can use specification parameters (like Get(specification)), which allow you to specify filters, orderings etc. without using data access language.

    Going back to the list of benefits of repository that you gave:

    • Persistence
    • OO View of the data
    • Data Access Logic Abstraction
    • Query Access Logic

    You can see that points 3 and 4 are not provided for by using the persistence framework classes directly, especially in real world retrieval scenarios.

    0 讨论(0)
提交回复
热议问题