13.07.2015 Views

C# in Depth

C# in Depth

C# in Depth

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

332 CHAPTER 12 LINQ beyond collections12.2.4 The fake query provider <strong>in</strong> actionList<strong>in</strong>g 12.8 shows a simple query expression, which (supposedly) f<strong>in</strong>ds all the str<strong>in</strong>gs<strong>in</strong> our fake source beg<strong>in</strong>n<strong>in</strong>g with “abc” and projects the results <strong>in</strong>to a sequence of thelengths of the match<strong>in</strong>g str<strong>in</strong>gs. We iterate through the results, but don’t do anyth<strong>in</strong>gwith them, as we know already that they’ll be empty. Of course, we have no sourcedata, and we haven’t written any code to do any real filter<strong>in</strong>g—we’re just logg<strong>in</strong>gwhich calls are made by LINQ <strong>in</strong> the course of creat<strong>in</strong>g the query expression and iterat<strong>in</strong>gthrough the results.List<strong>in</strong>g 12.8A simple query expression us<strong>in</strong>g the fake query classesvar query = from x <strong>in</strong> new FakeQuery()where x.StartsWith("abc")select x.Length;foreach (<strong>in</strong>t i <strong>in</strong> query) { }What would you expect the results of runn<strong>in</strong>g list<strong>in</strong>g 12.8 to be? In particular, whatwould you like to be logged last, at the po<strong>in</strong>t where we’d normally expect to do somereal work with the expression tree? Here are the results of list<strong>in</strong>g 12.8, reformattedslightly for clarity:FakeQueryProvider.CreateQueryExpression=FakeQuery.Where(x => x.StartsWith("abc"))FakeQueryProvider.CreateQueryExpression=FakeQuery.Where(x => x.StartsWith("abc")).Select(x => x.Length)FakeQuery.GetEnumeratorExpression=FakeQuery.Where(x => x.StartsWith("abc")).Select(x => x.Length)The two important th<strong>in</strong>gs to note are that GetEnumerator is only called at the end, noton any <strong>in</strong>termediate queries, and that by the time GetEnumerator is called we have allthe <strong>in</strong>formation present <strong>in</strong> the orig<strong>in</strong>al query expression. We haven’t manually had tokeep track of earlier parts of the expression <strong>in</strong> each step—a s<strong>in</strong>gle expression tree capturesall the <strong>in</strong>formation “so far” at any po<strong>in</strong>t <strong>in</strong> time.Don’t be fooled by the concise output, by the way—the actual expression tree isquite deep and complicated, particularly due to the where clause <strong>in</strong>clud<strong>in</strong>g an extramethod call. This expression tree is what LINQ to SQL would be exam<strong>in</strong><strong>in</strong>g to workout what query to execute. LINQ providers could build up their own queries (<strong>in</strong> whateverform they may need) as calls to CreateQuery are made, but usually look<strong>in</strong>g at thef<strong>in</strong>al tree when GetEnumerator is called is simpler, as all the necessary <strong>in</strong>formation isavailable <strong>in</strong> one place.The f<strong>in</strong>al call logged by list<strong>in</strong>g 12.8 was to FakeQuery.GetEnumerator, and you maybe wonder<strong>in</strong>g why we also need an Execute method on IQueryProvider. Well, not allquery expressions generate sequences—if you use an aggregation operator such as Sum,Licensed to Rhona Hadida

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!