Reputation: 86
Anyone here who can tell me explicitly about IEnumerable
and IQueryable
and the differences with the help of some examples?
Thanks
Upvotes: 3
Views: 770
Reputation: 156459
The IEnumerable<>
interface indicates that something can be enumerated across--in other words, you can do a foreach
loop on it.
The IQueryable<>
interface indicates that something has some kind of backing query provider that's capable of looking at Expressions that are given to it, and translate them into some kind of query.
It's easy to get confused by these, partly because IQueryable<>
extends IEnumerable<>
, and there is an extension method called .AsQueryable()
which can cause any IEnumerable<>
(like a List<>
to be converted into an IQueryable<>
.
There are a variety of extension methods known as "LINQ methods" in the Enumerable
and Queryable
classes in the System.Linq
namespace. They look almost exactly the same, and they are used with practically the same syntax, which further adds to your confusion, but there are some key differences. The ones on the Enumerable
class work on IEnumerable<>
objects and have signatures that take Func<>
s. The ones on the Queryable
class work on IQueryable<>
objects and have signatures that take Expression<Func<>>
s.
What's confusing about these is that the C# language will automatically infer whether you're trying to create an Expression<Func<>>
or a Func<>
based on context, so usage looks exactly the same in many cases. For example:
var e = new[]{1,2,3,4,5}.AsEnumerable();
var q = e.AsQueryable();
var eStrings = e.Select(i => i.ToString());
var qStrings = q.Select(i => i.ToString());
Those last two lines look the same, but they're actually doing very different things. The compiler is effectively producing the following code for you:
Func<int, string> eSelect = i => i.ToString();
var eStrings = e.Select(eSelect);
Expression<Func<int, string>> qSelect = i => i.ToString();
var qStrings = q.Select(qSelect);
If you did a .ToList()
on these results, the first one would simply call into the given Func<>
which is literally a function (you could have passed it a method name instead of a lambda expression, for example), for each item in the list. The second one would first have to compile the expression into a function first, and then call into that compiled expression.
Func<int, string> func = qSelect.Compile();
var s = func(1); // returns "1"
This is obviously more work. So why do we have IQueryable<>
s? Because there are some cases where knowing what somebody wanted to do is more important than actually running the code they gave you. For example, if you were using a provider like LINQ to Entities or LINQ to SQL, then running .ToList()
would cause this provider to look at the complete query, with its expressions intact, and recognize that what you wanted was to take the numbers and change them into strings. So a query like this:
var personIdStrings = Persons.Select(p => p.PersonId.ToString()).ToList();
... would actually cause an SQL string to be generated like this:
SELECT CONVERT(NVarChar,[t0].[PersonId]) AS [value]
FROM [Person] AS [t0]
... and then the SQL is sent to the database, and the results are transformed into a bunch of string
s. This is enormously powerful, and allows you to write normal C# code, and have it interpreted to mean different things depending on what provider is making the IQuerable<>
available to you.
Upvotes: 5
Reputation: 14417
I believe, IQueryable is for database querying. You can't use methods in an IQueryable either.
IEnumerable is just some that can be enumerated. So like a List or Array.
IQueryable:
_repository.All<MyModel>(); // can return a IQueryable from the database.
you can't have a method inside for instance, if ID were a GUID property you cant do this:
_repository.All<MyModel>(x => x.Id.ToString());
However, an IEnumerable is any kind of List or Array and methods can be used in them.
From MSDN for IQueryable:
Provides functionality to evaluate queries against a specific data source wherein the type of the data is known.
From MSDN for IEnumerable:
Exposes an enumerator, which supports a simple iteration over a non-generic collection.
Upvotes: 1
Reputation: 82267
There is a large difference between these two. Entity framework uses DbSet in order to expose an abstraction from linq to the database tables. This exposure comes in the form of an IQueryable. IQueryable implements the IEnumerable interface and allows for queried results to the database to be enumerated.
Enumeration forces the expression tree associated with an IQueryable object to be executed.
-MSDN: http://msdn.microsoft.com/en-us/library/vstudio/bb351562(v=vs.100).aspx
Basically IEnumerable is just a reference to the set of exposed methods involved with enumeration. You can see a full list of them at MSDN: IEnumerable.
Using an IQueryable object usually implies a reference to an active database connection. Any attempt to issue a query once the underlying connection has been disposed will throw an exception. As a result, it is important to ensure that IQueryable objects are never sent to a view or past the controller.
The enumeration can be forced by using a .ToList()
call, or .First()
, .Single()
, etc. which will force the information to be query to be enumerated.
Upvotes: 1