What is the difference between returning IQueryable
vs. IEnumerable
, when should one be preferred over the other?
In general terms I would recommend the following:
Return IQueryable<T>
if you want to enable the developer using your method to refine the query you return before executing.
Return IEnumerable
if you want to transport a set of Objects to enumerate over.
Imagine an IQueryable
as that what it is - a "query" for data (which you can refine if you want to). An IEnumerable
is a set of objects (which has already been received or was created) over which you can enumerate.
Yes, both use deferred execution. Let's illustrate the difference using the SQL Server profiler....
When we run the following code:
MarketDevEntities db = new MarketDevEntities();
IEnumerable<WebLog> first = db.WebLogs;
var second = first.Where(c => c.DurationSeconds > 10);
var third = second.Where(c => c.WebLogID > 100);
var result = third.Where(c => c.EmailAddress.Length > 11);
Console.Write(result.First().UserName);
In SQL Server profiler we find a command equal to:
"SELECT * FROM [dbo].[WebLog]"
It approximately takes 90 seconds to run that block of code against a WebLog table which has 1 million records.
So, all table records are loaded into memory as objects, and then with each .Where() it will be another filter in memory against these objects.
When we use IQueryable
instead of IEnumerable
in the above example (second line):
In SQL Server profiler we find a command equal to:
"SELECT TOP 1 * FROM [dbo].[WebLog] WHERE [DurationSeconds] > 10 AND [WebLogID] > 100 AND LEN([EmailAddress]) > 11"
It approximately takes four seconds to run this block of code using IQueryable
.
IQueryable has a property called Expression
which stores a tree expression which starts being created when we used the result
in our example (which is called deferred execution), and at the end this expression will be converted to an SQL query to run on the database engine.