linq to sql multiple Where() statements not creating a single expression
My understanding is that the following code:
IQueryable<Things> things = dataContext.Things.Take(10);
if (fromDate > new DateTime(1980, 1, 1))
things = things.Where(a => a开发者_StackOverflow.InsertedDate > fromDate);
if (toDate < defaultDate)
things = things.Where(a => a.InsertedDate < toDate);
should result in a query (assuming the dates pass the conditionals) like:
select top 10 [fields] from things
where inserteddate > '1/8/2010'
and inserteddate < '1/12/2010'
I've stepped through and confirmed that the two Where() statements are getting set, but when I call things.ToList(), I get the query:
select top 10 [fields] from things
Why aren't the two where's getting incorporated into the actual query getting run?
Your code is wrong. The call to Queryable.Take
should be at the end to get the query you want:
IQueryable<Things> things = dataContext.Things;
if (fromDate > new DateTime(1980, 1, 1))
{
things = things.Where(a => a.InsertedDate > fromDate);
}
if (toDate < defaultDate)
{
things = things.Where(a => a.InsertedDate < toDate);
}
things = things.Take(10);
When you call Take
first it finds the top ten elements from the entire database and then evaluates the Where cause for these 10 items only. The result would typically contain less than ten elements.
Your incorrect code could in theory be run as a single database query:
SELECT [fields]
FROM
(
SELECT TOP 10 [fields] FROM table1
) T1
WHERE inserteddate > '2010-01-08'
AND inserteddate < '2010-01-12'
It seems that this optimization has not been implemented. But I doubt that a query like this it is used very often.
Even though my example was instantiating the var as IQueryable, my actual code was doing so as IEnumerable. IEnumerable handles Where() differently apparently such that only the first expression will get executed against the DB and all subsequent ones do so in memory unlike IQueryable. I blame extension methods.
精彩评论