Posted in .NET Development, Tutorials

IEnumerable vs IQueryable – Part 1

What’s the difference between IQueryable and IEnumerable? This is probably the second most frequent question I’ve been asked (number 1 has to be understanding delegates).

The purpose of this article isn’t to formally define the interfaces, but rather to paint an easy to understand picture of how how do they differ. Then in Part 2 we get practical with 8 code snippet questions where we can test our understanding of the topic.

The Difference (Short answer)

  • IEnumerable – quering a collection in Memory
  • IQueryable – quering an External Data Source (most commonly a database)

What is IEnumerable?

The IEnumerable interface exposes an GetEnumerator method, which returns an IEnumerator interface which allows us to iterate through the collection. In plain English: an IEnumerable is a collection of items you can loop through.

Did you know, even arrays are inherently IEnumerable. See this snippet below:

int[] nums = { 1, 2, 3, 4 };
bool isEnumerable = nums is IEnumerable<int>; // True

IsEnumerable in the above code is true. This kind of makes sense, since an array (just like IEnumerable) is a collection of items we can loop through.

What makes IEnumerable special?

The most special thing about IEnumerable is that we can query items using LINQ.

There are a bunch of LINQ methods (Where, Select, Take, OrderBy, First etc.) which are simply extension methods for the IEnumerable interface. Same as all extension methods, just include the namespace (System.Linq) and the whole range of LINQ extensions are available to filter our collection.

Something else that’s very important to understand when using IEnumerable is Deferred Execution. In short, a LINQ Query only captures the intent. It holds off as long as it can and only does the actual filtering when any of the following happens:

  • Iterate the results (e.g. foreach)
  • Call ToList
  • Get a single result from the query (e.g. .Count() or .First())

Understanding Deferred Execution is key to using IEnumerable correctly. Not understanding this can lead to unnecessary performance issues. Check out Part 2 to see if you understand it correctly.

What is IQueryable?

Firstly IQueryable inherits from IEnumerable. This means inherently, it is also a collection of items that you can loop through. We can also write LINQ queries against an IQueryable.

IQueryable is used when querying a data source (let’s say a database).  So if we are using Entity Framework (EF), we can write a LINQ Query as follows and it will actually produce a SQL query:

EFQuery

In the above, our LINQ Query was translated to a SQL Query. When it is executed, the query will be run against our SQL database and return results to memory. Remember, the filtering does NOT happen in memory, but in the database (read this sentence again to make sure you’ve got it).

How does LINQ suddenly become SQL?

There are 2 important properties on the IQueryable interface: Expression and Provider

IQueryable

  • Expression – This is the Expression Tree built up from the LINQ Query
  • Provider – Tells us how to translate the Expression Tree into something else

In our case (using EF with a SQL database) what happened:

  • We created a simple LINQ query
  • This built up an Expression Tree
  • The Expression Tree gets passed to the Provider
  • Our provider translates the Expression Tree in SQL Query
  • As soon as we use our results (deferred execution), the SQL Query will execute against a database.
  • The results are returned and stored into memory.

Great uses for IQueryable

Think about the way IQueryable works for a moment. Let’s say we have a custom Data Source like a file which appends data with some separators we defined. If we find ourselves, constantly reading these files and trying to sift through the text to get hold of data;  we could instead use IQueryables and create our own Query Provider. This will allow us to write LINQ queries to get data from our files.

Another popular place IQueryable is used is for ASP.NET WebAPI OData. We can expose our REST endpoints and allow the person using our Web Service to filter only the data they need without pulling all data down to the client first. OData is basically just a standard that allows us to use URLs to filter specific data.

Example: Let’s say our REST service returns a list of 100 000 People: (http://mysite.com/People). But in our app we only want the people whose surnames contain the search text “Filter”.

Without the power of IQueryable and OData, we would either have to:

  • Pull all 100 000 people down to our client and then locally in memory filter for those 10 people with surname “Filter” that we actually need.
  • Or create an endpoint specfically for searching for people by surname, passing a query string parameter “Filter”.

Neither of these are great. But using Web API with OData, we could create a controller that returns IQueryable<Person> and then allow our app to:

  • Send a custom URL: http://mysite.com/People$filter=contains(Surname,’Filter’)
  • On the server, the IQueryable Expression Tree is built up from the OData URL
  • The Provider translates the Expression Tree to a SQL Query
  • The SQL executes against the database only getting 10 items from it
  • These 10 items are returned to app as the client’s requested format (e.g. JSON)

So with the power of IQueryable and OData, we indirectly queried the database via a URL, without having to write server code and didn’t have to pull data we did not need. (less bandwidth, less server processing and minimal client memory footprint)

Side note: LINQ Query Syntax vs Extension Methods

Not directly related to the topic, but a question I’ve been asked several times as well. Is it better to use Query Syntax or Extension methods.

Query Syntax:

var result = from n in nums
             where n > 2
             select n;

Extension Methods:

var result = nums.Where(n => n > 2);

They both compile down to the Extension Methods in the end. The Query syntax is simply a language feature added to simplify complex queries. Use which ever is more readable and maintainable for you.

I prefer to use Extension Methods for short queries and Query Syntax for complex queries.

Conclusion

If you missed everything, just remember this:

  • IEnumerable – queries a collection in Memory
  • IQueryable – queries an External Data Source (most commonly a database)

If you are comfortable with these interfaces, go to Part 2 and test yourself with 8 quick code snippet questions on the topic.

Author:

I am enthusiastic about technology and people. I especially have a passion for imparting things I have learnt over my career or am in the process of learning. A strong desire of mine is to empower bright youngsters with potential (especially those from a disadvantaged background). I'm privileged to be in expanding industry that seems to always be looking for new talent and the opportunities are countless for those willing to apply themselves to the trade. https://filteredcode.co.za

6 thoughts on “IEnumerable vs IQueryable – Part 1

    1. Yes you’re right, IQueryable can point to an in-memory source and I can imagine this might cause confusion. Fortunately however, to my knowledge this can only every happen when we explicitly cast an already in-memory IEnumerable collection to IQueryable.

      An interesting question would be why did someone create the AsQueryable() extension method on IEnumerable?
      – Only reasonable answer I can think of is to easily mock out IQueryable’s in unit tests by having an in-memory source instead of the overhead of creating an external data source.
      – Or possibly write a “filtering” method accepting IQuerable and passing both in-memory and external sources through it. This sounds neat, but IMHO from trying something similar before, feels like a a code smell more than an advantage.

      Thanks for the comment.

      Liked by 1 person

  1. I once was curious to see if I could change IQueryable to IN-Memory collection, perform some operations, and convert back to IQueryable to perform some more joins from the database side, but it failed, as expected. Interesting.

    Like

  2. This is an excellent article. To the point. Exactly what I was looking for. My search started with why OData is better for querying, and then got diverted to understanding IEnumerable vs IQueryable. Your article hits the bull eye for my questions. Great one!

    Like

Leave a comment