I have the following Linq to Objects query:
var query = this._vaporizerData
.Where(row => row.Coater == coater)
.Where(row => row.Distributor == distributor)
.Where(row => row.PowerTubeA.HasValue);
if (query.Any())
{
tubeA = query
.Where(row => row.CoaterTime.Value >= readTime.AddMinutes(-5))
.Where(row => row.CoaterTime.Value <= readTime)
.OrderByDescending(row => row.CoaterTime)
.Select(row => row.PowerTubeA)
.First()
.Value;
}
I know that when the query.Any() line is executed, the first Linq query is evaluated. My question is this. Let’s assume the results of the first query is 5 rows of data. When I execute the second query (starting with ‘tubeA = query’), am I correct it will evaluate this against just the five rows returned from the first query?
Thanks very much.
Well, sort of. It’s evaluated as far as necessary. So if you have a million rows in
_vaporizerDatabut the first of them matches the filter, it’s not going to iterate over the rest of the data.Yes, but it will have to find those rows again, checking the filter against all the rows which didn’t match the first time. So again, if you have a million rows in
_vaporizerDatabut this time only the last row matches the original query, you’ll end up checking against all the 999,999 non-matching rows again.Also, if anything else changes the contents of
_vaporizerDatabetween the call toAny()and the call toFirst(), those changes will be visible, as it really is going back to the original data source.It would be better to only execute the query once, e.g.
EDIT: Two important points noted in comments:
resultas null. That may or may not be an issue for you..MaxBy(row => row.CoaterTime)instead of usingOrderByDescendingandFirst. IIRC, that will fail on an empty input though, so you should only do this if you’re using your original version withFirst, not the version above.