Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why the order of LINQ to objects methods counts

I read this question's answers that explain the order of the LINQ to objects methods makes a difference. My question is why?

If I write a LINQ to SQL query, it doesn't matter the order of the LINQ methods-projections for example:

session.Query<Person>().OrderBy(x => x.Id)
                       .Where(x => x.Name == "gdoron")
                       .ToList();

The expression tree will be transformed to a rational SQL like this:

  SELECT   * 
  FROM     Persons
  WHERE    Name = 'gdoron'
  ORDER BY Id; 

When I Run the query, SQL query will built according to the expression tree no matter how weird the order of the methods.
Why it doesn't work the same with LINQ to objects?
when I enumerate an IQueryable all the projections can be placed in a rational order(e.g. Order By after Where) just like the Data Base optimizer does.

like image 851
gdoron is supporting Monica Avatar asked Dec 21 '11 19:12

gdoron is supporting Monica


People also ask

Does LINQ preserve order?

Therefore, by default, PLINQ does not preserve the order of the source sequence. In this regard, PLINQ resembles LINQ to SQL, but is unlike LINQ to Objects, which does preserve ordering.

What is default order by in LINQ?

In LINQ, the OrderBy operator is used to sort the list/ collection values in ascending order. In LINQ, if we use order by the operator by default, it will sort the list of values in ascending order.

Does ToList preserve order?

The simple answer is no, ToList will just loop over the source enumerable and keep the same order.

Which method is valid in LINQ?

Most of the LINQ projection and restriction methods are supported in LINQ to Entities queries, with the exception of those that accept a positional argument. For more information, see Standard Query Operators in LINQ to Entities Queries.


2 Answers

Why it doesn't work this way with LINQ to objects?

LINQ to Objects doesn't use expression trees. The statement is directly turned into a series of method calls, each of which runs as a normal C# method.

As such, the following in LINQ to Objects:

   var results = collection.OrderBy(x => x.Id)
                   .Where(x => x.Name == "gdoron")
                   .ToList();

Gets turned into direct method calls:

   var results = Enumerable.ToList(
                   Enumerable.Where(
                     Enumerable.OrderBy(collection, x => x.Id),
                     x => x.Name = "gdoron"
                   )
                 );

By looking at the method calls, you can see why ordering matters. In this case, by placing OrderBy first, you're effectively nesting it into the inner-most method call. This means the entire collection will get ordered when the resutls are enumerated. If you were to switch the order:

   var results = collection
                   .Where(x => x.Name == "gdoron")
                   .OrderBy(x => x.Id)
                   .ToList();

Then the resulting method chain switches to:

   var results = Enumerable.ToList(
                   Enumerable.OrderBy(
                     Enumerable.Where(collection, x => x.Name = "gdoron"),
                     x => x.Id
                   )
                 );

This, in turn, means that only the filtered results will need to be sorted as OrderBy executes.

like image 76
Reed Copsey Avatar answered Oct 30 '22 09:10

Reed Copsey


Linq to objects's deferred execution works differently than linq-to-sql's (and EF's).

With linq-to-objects, the method chain will be executed in the order that the methods are listed—it doesn't use expression trees to store and translate the whole thing.

Calling OrderBy then Where with linq-to-objects will, when you enumerate the results, sort the collection, then filter it. Conversely, filtering results with a call to Where before sorting it with OrderBy will, when you enumerate, first filter, then sort. As a result the latter case can make a massive difference, since you'd potentially be sorting many fewer items.

like image 34
Adam Rackis Avatar answered Oct 30 '22 07:10

Adam Rackis