Nested from LINQ query expressed with extension methods
For your future reference, all questions of this form are answered by section 7.16 of the C# specification.
Your specific question is answered by this paragraph:
A query expression with a second from
clause followed by a select
clause
from x1 in e1
from x2 in e2
select v
is translated into
( e1 ) . SelectMany( x1 => e2 , ( x1 , x2 ) => v )
So your query:
var query = from a in sequenceA
from b in sequenceB
select ...;
Is the same as
var query = ( sequenceA ) . SelectMany( a => sequenceB , ( a , b ) => ... )
(Note that of course this assumes that the "..." is an expression, and not, say, an expression followed by a query continuation.)
hdv's answer points out that
var query = ( sequenceA ) . SelectMany(
a => ( sequenceB ) . Select( b => ... ) );
would also be a logically valid translation, though it is not the translation we actually perform. In the early days of LINQ implementation, this was the translation we chose. However, as you pile on more from
clauses, it makes the lambdas nest more and more deeply, which then presents the compiler with an enormous problem in type inference. This choice of translation wrecks compiler performance, so we introduced the transparent identifier mechanism to give us a much cheaper way to represent the seamntics of deeply nested scopes.
If these subjects interest you:
For more thoughts on why deeply nested lambdas present a hard problem for the compiler to solve, see:
http://blogs.msdn.com/b/ericlippert/archive/2007/03/26/lambda-expressions-vs-anonymous-methods-part-four.aspx
http://blogs.msdn.com/b/ericlippert/archive/2007/03/28/lambda-expressions-vs-anonymous-methods-part-five.aspx
For more information about transparent identifiers, see this post from Wes Dyer, who implemented them in C# 3.0:
http://blogs.msdn.com/b/wesdyer/archive/2006/12/22/transparent-identifiers.aspx
And my series of articles about them:
http://ericlippert.com/2014/07/31/transparent-identifiers-part-one/
Convert linq query expression with multiple froms into extension method syntax
var query = _context.Customer
.Where(c => c.Orders.Any(o => o.DateSent == null))
.Select(c => new CustomerSummary
{
Id = c.Id,
Username = c.Username,
OutstandingOrderCount = c.Orders.Count(o => o.DateSent == null)
};
Creating Extension method to include subquery
I found an other way of returning the same result using a Generic Way.
public static IQueryable IncludeTranslation<S>(this IQueryable<S> source, Expression<Func<S, string>> keyField)
where S : class
{
IQueryable<CFG_TRANSLATION> translations = GetTranslations();
var trans = source.GroupJoin(translations, keyField, t => t.TR_TEXT, (s, t) => new { Source = s, Translations = t });
var result = trans.Select(t => new {
Source = t.Source,
Translation = t.Translations
.FirstOrDefault()
});
return result;
}
Maybe someone can use this as a sollution
this can be called as follow
var Result = QueryableTable.IncludeTranslation(t => t.FieldToTranslate);
LINQ-to-SQL and Extension method in subQuery
When i use my extension method in a simple query, it's working, but when i use it in a sub query it's not working. Any solutions ?
Working
var test = from pl in t.ProductLocales.FilterCultureSubQuery() select pl;
Not Working
var test = from p in t.Products
select new
{
Allo = p,
Allo2 = (from pl in t.ProductLocales.FilterCultureSubQuery()
select pl)
};
I create a new extension method and rewrite the expression tree of the query.
var test = (from p in t.Products
select new
{
Allo = p,
Allo2 = (from pl in t.ProductLocales.FilterCultureSubQuery()
select pl)
}).ArrangeExpression();
LINQ-TO-SQL have difficulty to use extension method in subquery. With a rewrite expression extension method everyting working fine.
Any other solutions ?
How to convert Linq-to-objects query with two from clauses to method syntax
Two consecutive from
-clauses are translated with a SelectMany
extension method:
var occupiedSquares = squares
.SelectMany(s => pieces.Select(p => (s, p))) // Creates a ValueTuple
.Where(x => Occupies(x.p, x.s))
.Select(x => x.s);
If you are working with an older Framework version, you can also use an Anonymous Type instead of a ValueTuple.
var occupiedSquares = squares
.SelectMany(s => pieces.Select(p => new { s, p }))
.Where(x => Occupies(x.p, x.s))
.Select(x => x.s);
Alternatively, you can also apply the Where-clause to the nested Select
. No aggregate (ValueTuple
or anonymous type) is required in this case:
var occupiedSquares = squares
.SelectMany(
s => pieces
.Where(p => Occupies(p, s))
.Select(p => s)
);
The Enumerable.SelectMany Method is typically used to flatten a nested collection. E.g., you have a list of users and the user objects have a list of posts and you need a list of all the posts.
See also my question Nested “from” LINQ query expressed with extension methods and Eric Lippert's answer. (Eric was part of Microsoft's C# compiler team.)
LinqKit applying nested filtering through extension-method not working
You have to mark your Get
method as expandable:
[Expandable(name(GetEnumerable))]
public static IEnumerable<TEntity> Get<TEntity, TEntityFilter>(this IEnumerable<TEntity> entities, TEntityFilter filter)
where TEntity : BaseEntity<TEntity>, new()
where TEntityFilter : EntityFilter<TEntity>
{
return entities.Where(e => filter.FilterExpression.Expand().Invoke(e));
}
private static Expression<Func<IEnumerable<TEntity>, TEntityFilter, IEnumerable<TEntity>>> GetEnumerablet<TEntity, TEntityFilter>()
{
return (entities, filter) =>
entities.Where(e => filter.FilterExpression.Expand().Invoke(e));
}
Multiple from clauses in LINQ
Enumerable.Range(1, 3).SelectMany(
i => Enumerable.Range(4, 3),
(i, j) => new Tuple<int, int>(i, j)
).ToList();
Multiple WHERE Clauses with LINQ extension methods
Two ways:
results = results.Where(o => (o.OrderStatus == OrderStatus.Open) &&
(o.CustomerID == customerID));
or:
results = results.Where(o => (o.OrderStatus == OrderStatus.Open))
.Where(o => (o.CustomerID == customerID));
I usually prefer the latter. But it's worth profiling the SQL server to check the query execution and see which one performs better for your data (if there's any difference at all).
A note about chaining the .Where()
methods: You can chain together all the LINQ methods you want. Methods like .Where()
don't actually execute against the database (yet). They defer execution until the actual results are calculated (such as with a .Count()
or a .ToList()
). So, as you chain together multiple methods (more calls to .Where()
, maybe an .OrderBy()
or something to that effect, etc.) they build up what's called an expression tree. This entire tree is what gets executed against the data source when the time comes to evaluate it.
Related Topics
Suppress Properties with Null Value on ASP.NET Web API
Write an Rx "Retryafter" Extension Method
Minimizing All Open Windows in C#
Why Does C# Disallow Readonly Local Variables
Show a Child Form in the Centre of Parent Form in C#
Multi-Tenant with Code First Ef6
Performance of Find() VS. Firstordefault()
Could We Save Delegates in a File (C#)
Who Should Call Dispose on Idisposable Objects When Passed into Another Object
Button Inside a Winforms Textbox
How to Read Single Excel Cell Value
Memory Efficiency and Performance of String.Replace .Net Framework
Equivalence of "With...End With" in C#
How to Reference Microsoft.Office.Interop.Excel Dll