IQueryable vs List: What Should Your Repository Return?

Thursday, February 28, 2013 @ 02:41

By: Corey Adler, Staff Developer

IQueryable vs List: What Should Your Repository Return?

In an earlier blog post (located at http://www.paragon-inc.com/resources/blogs-posts/the-repo-man), I described two reasons why you should use repositories on top of your Entity Framework. If you’ve decided to take my advice on that, then you should know something before you get too far into it. There exists a lot of discussion in blogs and Stack Overflow questions as to what exactly some of your repository methods should return. Should they return IQueryable<T>? What about going straight to a List<T>? Let’s take a look at both of them and their respective advantages.

Figure 1: The repository interface. Note the return types for the Grab and All methods.

IQueryable<T>: IQueryable is actually part of the System.Linq namespace itself, and extends IEnumerable. IEnumerable is the standard return of many LINQ extension methods, including Select, Where, Distinct, and others. IQueryable takes IEnumerable and adds some other, query-specific, features on top of this—such as being able to grab the specific expression tree that represents the LINQ query being used. More information on IQueryable can be found at: http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx

List<T>: List is probably the most well-known collection type, with implementations in multiple object-oriented languages, including C# and Java. Like IQueryable, List extends IEnumerable. Unlike IQueryable, the methods that are baked into List deal exclusively with the elements found inside the list itself, rather than how they were put there. Also like IQueryable, List is not part of the System.Linq namespace, although one can still use LINQ operators on it. More information can be found at: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx .

So what are their respective advantages?

For IQueryable, the biggest advantage is the fact that it employs deferred execution. Deferred Execution means that the query itself is not executed right away when it is constructed. It is only when the data that the query is calling for is needed that the query itself actually executes. The methods that use deferred execution can be found at: http://msdn.microsoft.com/en-us/library/bb882641.aspx . List, however, executes the query right away. This can present the problem of slowing down business logic code that would otherwise have been run before the query was run. IQueryable also allows you to append query functions—such as OrderBy, Take, or other Where clauses—to the collection before it goes to the database. By the time the data is in a List, however, the query will have already been executed, typically leading to situations with non-optimized code that grabs too much from the database—thus making the application that much slower.

For List, the biggest advantage is that you don’t need to worry about your DbContext already being disposed before you get a chance to run the query. I have seen many a question on Stack Overflow about the dreaded ObjectContextDisposed exception, most of which are resolved by using .ToList() before the DbContext gets disposed—this returns the data itself, thus no longer requiring the context to go back to the database. If the repository itself returns List, then, there would be no need to worry about the context being disposed. The other advantage is that List means that you don’t have to expose any part of your database query to the client-side code. This can be a big deal if you want to properly enforce separation of concerns. The database logic will stay in your repository, meaning that any data errors will be located there instead of having to fish through your client-side code as well for the error.

Deciding between IQueryable and List is not something trivial. It can impact both the design and implementation of your project, and is not something to be taken lightly. For myself, I prefer to use IQueryable, because even though it can expose the query to the client-side, I much prefer the wonders of deferred execution in my applications. I‘ll leave it up to you to decide which side of this coin is better for your own needs. Until then, I wish you good coding.