Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
799 views
in Technique[技术] by (71.8m points)

c# - Where clause not working on LINQ IQueryable query

Using Linq to Entities, the where clause is not working when I do a Where lamba expression on a Linq object created with a written LINQ statement.

This does not work. Query executes, but results are returned unfiltered.

var myQuery = (from l in db.MyTable
                     select l);
myQuery.Where(r => availableStatusList.Contains(r.Status));
var myObj = myQuery.ToList();  

This does work. Query executes, AND results are returned filtered properly.

var myQuery = (from l in db.MyTable
                     select l).Where(r => availableStatusList.Contains(r.Status));
var myObj = myQuery.ToList();

As far as I understand, both of these should return equivalent results. Any reason why the first one does not listen to the Where clause?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A Where clause does not create a new object when invoked; it applies a filter to an existing collection by wrapping the collection in a filter that will eventually be run. However, since it is a pure function, the return value of that filter needs to be returned to the original reference myQuery, which is why the second example works...you have chained the result through the Where() clause back to myQuery. You return the filtered collection back, materializing the deferred query with ToList().

In the first example, you are assuming that the filter is applied directly to the collection, but that isn't how LINQ works, since the filter doesn't modify the collection immediately when the function is called. Rather, it only applies a predicate that WILL be applied provided it is "attached" to the original Queryable collection and you resolve the query with ToList().

It is sometimes easier to think about deferred execution as a series of promises.

If I give you a dollar, you have a dollar. If I take 25 cents for taxes, I've immediately resolved our transaction (query).

However, if I promise to give you a dollar on Tuesday, I've returned a Queryable<T> promise.

Multiple events could occur however between now and Tuesday. I could chain a filter for taxes (25 cents), a filter for a stick of gum (25 cents), or any other filter.

However, our bookkeeping system has a caveat. We can't just call .Taxes() (our Where clause) on the total promised amount and expect it to update. We have to record our transaction against the promised amount by returning the filter to the original variable, updating it with the transaction that has occurred against our promised amount.

myQuery = myQuery.Where(condition);

On Tuesday, when you come to collect your payment (by calling ToList() on the series of chained promises/filters), I deduct what has occurred from what was promised, resulting in a 50 cent payout. That's deferred execution at work.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...