List<Device> deviceList = GetDevices(); // these are loaded in memory already as a list
IQueryable<Device> IDevices = deviceList.AsQueryable<Device>();
deviceList = IDevices.Where(i => i.StatusID == 2).OrderBy(j => j.LastCommunicated).Skip(recordsToSkip).Take(pageSize).ToList();
Given the above code, I have about 1000 devices in the list being queried on. The 3rd statement is very slow. Shouldn't it be fast if it is loaded into memory already? I understand in most scenarios you would apply the whole query to the database call, but in my case I already have my devices loaded in memory. The 1st and 2nd calls are very quick.
We can implement the paging using the Linq Skip and Take method.
IEnumerable: IEnumerable is best suitable for working with in-memory collection (or local queries). IEnumerable doesn't move between items, it is forward only collection. IQueryable: IQueryable best suits for remote data source, like a database or web service (or remote queries).
The IQueryable interface inherits the IEnumerable interface so that if it represents a query, the results of that query can be enumerated. Enumeration causes the expression tree associated with an IQueryable object to be executed. The definition of "executing an expression tree" is specific to a query provider.
In LINQ to query data from database and collections, we use IEnumerable and IQueryable for data manipulation. IEnumerable is inherited by IQueryable, Hence IQueryable has all the features of IEnumerable and except this, it has its own features. Both have its own importance to query data and data manipulation.
IQueryable
is irrelevant at that point. The performance issue you're seeing is that each chain returns a new iterator.
So, this:
IDevices
.Where(i => i.StatusID == 2) // iterates over 1000 items
.OrderBy(j => j.LastCommunicated) // orders however many items have a StatusID of 2
.Skip(recordsToSkip) // iterates "recordsToSkip" number of times
.Take(pageSize) // iterates "pageSize" times
Is a step by step process. First, Where
executes. This iterates over the entire list. Then OrderBy
executes, which as you can imagine is quite intensive. Skip
then iterates through until it finds the index you want to be at. Take
then iterates over n items before you form a new list.
That being said.. had you just run this query straight against the database, it would have been much quicker.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With