3

I am currently refactoring my code for a web application developed using ASP.NET MVC3 with C# and Razor. One of the pattern I am using in order to better structure my application is the Repository pattern, which, besides being a really useful pattern, is also a frequent matter of discussion within the developers' community.

In this context I found an article by Fredrik Normen which states that, according to the definition of Repository,a repository class must provide actual entities (for instance List in .NET) and not queriable objects (IQueriable in .NET). Instead in the NerdDinner tutorial from ASP.NET MVC official website they use IQueriable when the Repository has to provide multiple instances of the same object and the actual entity when the repository has to provide a single instance of the object.

What is the most correct approach to use when modeling a repository class/interface according to the Repository pattern?

Thanks

Francesco

CiccioMiami
  • 8,028
  • 32
  • 90
  • 151
  • possible duplicate: http://stackoverflow.com/questions/1699607/asp-mvc-repository-that-reflects-iqueryable-but-not-linq-to-sql-ddd-how-to-ques – Mark Seemann Apr 12 '11 at 10:31

2 Answers2

4

In my opinion this sort of thing is detrimental to the use of your time. ;-)

In theory, your repository should return objects or traditional collections of them, yes. However, even the definition of the repository pattern you link to uses the term "collection-like interface". Certainly, an IQueryable<Entity> is a 'collection-like' interface, yes?

In practice, I almost never think about the distinction... but I always try to put all of the querying code in the repository. I'd say 90% of my collection-based repository methods return traditional collections, while the other 10% return something based on IQueryable<>. The exceptions usually have to do with paging; so I can get the totals from the query down the line if needed, and not have to get that info early if I don't need it. It's a little lazy, but it works for me.

But I do think it's a good idea to always try to return traditional collections, because that will mean you are encapsulating all of your querying in the repository, which is where it should be. I would recommend just not to get too caught up in the extreme levels of adhering to someone's idea of what the requirement is for pattern-X

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • thanks for your answer. I agree that during the first stages of development you care more about making your application functional and it is more convinient to make some queries outside the repository. But when you refactor you always try to adhere to guidelines and patterns that enhance the quality of your application. Currently my application use database to store/get data but in the future will use web services. I was wondering about the most convinient approach to repository, between the two listed above, that will reduce the efforts of this "replacement". Thanks – CiccioMiami Apr 12 '11 at 09:38
  • There really is no "difference", per-se, at all. The Nerd Dinner application does not do querying outside of the repository, to my recollection. If it does, it's probably just illustrating some other point. Keep your querying code in the repository, yes; Just don't worry quite as much about the exact semantics of exactly what kind of "collection-like interface" is being returned. If you like the stricter requirement, you will do well if you adhere to it, though. – Andrew Barber Apr 12 '11 at 09:40
1

Opinions will differ on that, as you've already found. For small scale applications it's probably OK to let your repositories expose IQueryable.

One thing that you certainly should not do is pass IQueryable to your views. Make sure your views receive only materialized objects and collections (like List or arrays). This way if an error exists in a query somewhere, it will occur in the controller (or repository) and not in your view. This enables you to test the queries and handle errors gracefully.

Marnix van Valen
  • 13,265
  • 4
  • 47
  • 74
  • Why not pass to views? What's the difference? Does that make abstraction to leak less? – Arnis Lapsa Apr 12 '11 at 09:23
  • @Marnix van Valen: thanks for your answer. I always force myself not to use the ViewData and use ViewModels instead, to enhance testing. I think this is the best way to avoid passing IQueriables to the View. May you please specify what you consider ha _"small scale application"_? Thanks – CiccioMiami Apr 12 '11 at 09:40
  • @Arnis IQueryable may do lazy evaluation, depending on the query and storage underneath. Worst case it will do multiple queries to your database while rendering your view. There's a whole lot of things that can go wrong there. You may want to read [this article](http://www.weirdlover.com/2010/05/11/iqueryable-can-kill-your-dog-steal-your-wife-kill-your-will-to-live-etc/) for more information. – Marnix van Valen Apr 12 '11 at 12:04
  • @Francesco _small scale_ for me is a quick and dirty application like a proof of concept to demo some ideas. It may also be an app that I alone work on and that will never leave my company. For example I recently built a small migration tool to upgrade an application from one version to another. The source code will be removed from the source tree the next release. As soon as code is going to be worked on by more than one person or live longer than a couple of months I stick to the rules, no exceptions. – Marnix van Valen Apr 12 '11 at 12:13
  • @Marnix my point was - what's the difference between exposing `IQueryable` to service/controller layer vs exposing further to view layer? I mean - exposing such an abstraction is bad in both cases. – Arnis Lapsa Apr 12 '11 at 13:00
  • @Arnis Sorry, I misunderstood you there. You're right it's bad in both cases. – Marnix van Valen Apr 12 '11 at 13:43