The Linq Query Sintax is a SQL-like syntax provided as a short hand method for invocation, that at compile time will be parsed and converted to the Standard Query Operators.
query-expression ::= from-clause query-body query-body ::= query-body-clause* final-query-clause query-continuation? query-body-clause ::= (from-clause | join-clause | let-clause | where-clause | orderby-clause) from-clause ::= from itemName in srcExpr join-clause ::= join itemName in srcExpr on keyExpr equals keyExpr (into itemName)? let-clause ::= let itemName = selExpr where-clause ::= where predExpr orderby-clause ::= orderby (keyExpr (ascending | descending)?)* final-query-clause ::= (select-clause | groupby-clause) select-clause ::= select selExpr groupby-clause ::= group selExpr by keyExpr query-continuation ::= into itemName query-body
The INTO keyword essentially allows one to continue a query after a projection by taking the result retrieved from GROUP, JOIN or SELECT clauses and places it into the a new temporary variable which then allows one to introduce additional WHERE, ORDERBY, and SELECT clauses.
Once the INTO variable is used then a new context/scope is used and the previous variable(s) are no longer available in the query.
In the Methods Sintax the INTO keyword is converted to a GROUPJOIN operator.
The LET keyword uses temporary anonymous types that are injected into the context/scope and allow to reuse more than one variable at a time: The variable value can be passed forward to the WHERE and ORDERBY operations without duplicate calls.
Examples of use:
1. To create an enumerable type that can itself be queried in subsequent clauses;
2. Apply a function to an enumerable instead of each predicate in the where clause.
In the Methods Sintax the LET keyword is equivalent to the use of a intermediate SELECT operator that will create an anonynous tuple with:
1) the original selected item; and
2) the new injected value.