score:23
Short answer
You should do what you feel is more readable and maintainable in your application as both will evaluate to the same collection.
Long answer quite long
Linq To Objects
ATable.Where(x=> condition1 && condition2 && condition3)
For this example Since there is only one predicate statement the compiler will only needs to generate one delegate and one compiler generated method.
From reflector
if (CS$<>9__CachedAnonymousMethodDelegate4 == null)
{
CS$<>9__CachedAnonymousMethodDelegate4 = new Func<ATable, bool>(null, (IntPtr) <Main>b__0);
}
Enumerable.Where<ATable>(tables, CS$<>9__CachedAnonymousMethodDelegate4).ToList<ATable>();
The compiler generated method:
[CompilerGenerated]
private static bool <Main>b__0(ATable m)
{
return ((m.Prop1 && m.Prop2) && m.Prop3);
}
As you can see there is only one call into Enumerable.Where<T>
with the delegate as expected since there was only one Where
extension method.
ATable.Where(x=>condition1).Where(x=>condition2).Where(x=>condition3)
now for this example a lot more code is generated.
if (CS$<>9__CachedAnonymousMethodDelegate5 == null)
{
CS$<>9__CachedAnonymousMethodDelegate5 = new Func<ATable, bool>(null, (IntPtr) <Main>b__1);
}
if (CS$<>9__CachedAnonymousMethodDelegate6 == null)
{
CS$<>9__CachedAnonymousMethodDelegate6 = new Func<ATable, bool>(null, (IntPtr) <Main>b__2);
}
if (CS$<>9__CachedAnonymousMethodDelegate7 == null)
{
CS$<>9__CachedAnonymousMethodDelegate7 = new Func<ATable, bool>(null, (IntPtr) <Main>b__3);
}
Enumerable.Where<ATable>(Enumerable.Where<ATable>(Enumerable.Where<ATable>(tables, CS$<>9__CachedAnonymousMethodDelegate5), CS$<>9__CachedAnonymousMethodDelegate6), CS$<>9__CachedAnonymousMethodDelegate7).ToList<ATable>();
Since we have three chained Extension methods we also get three Func<T>
s and also three compiler generated methods.
[CompilerGenerated]
private static bool <Main>b__1(ATable m)
{
return m.Prop1;
}
[CompilerGenerated]
private static bool <Main>b__2(ATable m)
{
return m.Prop2;
}
[CompilerGenerated]
private static bool <Main>b__3(ATable m)
{
return m.Prop3;
}
Now this looks like this should be slower since heck there is a ton more code. However since all execution is deferred until GetEnumerator()
is called I doubt any noticeable difference will present itself.
Some Gotchas that could effect performance
- Any call to GetEnumerator in the chain will cause a the collection to be iterated.
ATable.Where().ToList().Where().ToList()
will result in an iteration of the collection with the first predicate when theToList
is called and then another iteration with the secondToList
. Try to keep the GetEnumerator called to the very last moment to reduce the number of times the collection is iterated.
Linq To Entities
Since we are using IQueryable<T>
now our compiler generated code is a bit different as we are using Expresssion<Func<T, bool>>
instead of our normal Func<T, bool>
Example in all in one.
var allInOneWhere = entityFrameworkEntities.MovieSets.Where(m => m.Name == "The Matrix" && m.Id == 10 && m.GenreType_Value == 3);
This generates one heck of a statement.
IQueryable<MovieSet> allInOneWhere = Queryable.Where<MovieSet>(entityFrameworkEntities.MovieSets, Expression.Lambda<Func<MovieSet, bool>>(Expression.AndAlso(Expression.AndAlso(Expression.Equal(Expression.Property(CS$0$0000 = Expression.Parameter(typeof(MovieSet), "m"), (MethodInfo) methodof(MovieSet.get_Name)), ..tons more stuff...ParameterExpression[] { CS$0$0000 }));
The most notable is that we end up with one Expression tree that is parsed down to Expression.AndAlso
pieces. And also like expected we only have one call to Queryable.Where
var chainedWhere = entityFrameworkEntities.MovieSets.Where(m => m.Name == "The Matrix").Where(m => m.Id == 10).Where(m => m.GenreType_Value == 3);
I wont even bother pasting in the compiler code for this, way to long. But in short we end up with Three calls to Queryable.Where(Queryable.Where(Queryable.Where()))
and three expressions. This again is expected as we have three chained Where
clauses.
Generated Sql
Like IEnumerable<T>
IQueryable<T>
also does not execute until the enumerator is called. Because of this we can be happy to know that both produce the same exact sql statement:
SELECT
[Extent1].[AtStore_Id] AS [AtStore_Id],
[Extent1].[GenreType_Value] AS [GenreType_Value],
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[MovieSet] AS [Extent1]
WHERE (N'The Matrix' = [Extent1].[Name]) AND (10 = [Extent1].[Id]) AND (3 = [Extent1].[GenreType_Value])
Some Gotchas that could effect performance
- Any call to GetEnumerator in the chain will cause a call out to sql, e.g.
ATable.Where().ToList().Where()
will actually query sql for all records matching the first predicate and then filter the list with linq to objects with the second predicate. - Since you mention extracting the predicates to use else where, make sure they are in the form of
Expression<Func<T, bool>>
and not simplyFunc<T, bool>
. The first can be parsed to an expression tree and converted into valid sql, the second will trigger ALL OBJECTS returned and theFunc<T, bool>
will execute on that collection.
I hope this was a bit helpful to answer your question.
Source: stackoverflow.com
Related Query
- linq styling, chaining where clause vs and operator
- C# - Linq optimize code with List and Where clause
- How to dynamically add OR operator to WHERE clause in LINQ
- How to combine Where clause and group by in LINQ
- linq where clause and count result in null exception
- Ternary operator in LINQ where clause
- Linq where clause with multiple conditions and null check
- Linq with where clause in many-to-many EF Code First object
- Dynamic Linq and Where Clause & NOT Contains
- Can SELECT and WHERE LINQ clause be combined?
- Ternary Operator in LINQ Where clause for nullable bool column
- Where Clause in LINQ with IN operator in Vb
- LINQ Group by and having where clause
- LinQ query Simple Where clause and many filter criteria
- LINQ query - join and where clause not being obeyed?
- Where clause in Linq and compare strings
- Groupby and where clause in Linq
- Using Linq to query Entity Framework with Where clause and many-to-many relation
- Linq Include and Where Clause
- C# Linq use Where with IsNull() Operator '&&' cannot be applied to operands of type 'bool' and 'int?'
- Entity Framework Core Not Generating Where Clause When Using LINQ and predicate
- Computational and stylistic optimal solution for the conditional where clause using Linq
- How to AND predicates in the WHERE clause in a LINQ to RavenDB query
- Linq how to join tables with a where clause on each table and a count
- Linq Query using navigation properties and Where clause
- LINQ where clause using Generic IQueryable source
- Adding AND in a WHERE clause using ViewBag and SelectList with LINQ in Controller (ASP.Net MVC)
- LINQ query to conditionally filter on a where clause and select the values from another table
- Entity Framework: Linq where clause compare date and time value with seconds difference
- Linq query with cartesian (wanted) and min/max in where clause
More Query from same tag
- Combining two adjacent collections to create Json rows
- Update all cells of a datatable in one go in c#
- LINQ - Joining 3 tables and selecting an item with two lists
- Conditionally Populate Class Field in LINQ To Entities
- Adding items to sub-array of an array doesn't work
- QueryOver in NHibernate
- Find Something in List of Objects, where object value is equal to string
- Reuse stored procedure result in linq to sql in Code First
- c# refactoring with linq query
- How to query values associated with the foreign key using linq and display in listview
- LINQ query in C# using group and join
- XML elements to Tuple using LINQ in C#
- Linq Order By 2 fields in on condition
- How can I check for a null inside of a linq query?
- Error when joining two tables using linq in mvc4
- Strange behavior in Thread
- WP7 Trouble populating pie chart
- Custom aggregation functions in SQL Server vs Aggregate in Linq
- List Operations without ForLoops
- Sort and Order Alphabetically
- Azure IListBlobItem Oftype CloudBlob Linq Change List<CloudBlob>
- Equivalent of Right() function
- In LINQPad can you access SYSOBJECTS using LINQ?
- LINQ Submit Changes not submitting changes
- LINQ group by date like today, tomorrow into keyed list
- List.OrderByDescending results in duplicates
- LINQ to Entities, join two tables, then group and take sums of columns from both tables
- Executing stored procedures in parallel.foreach .net
- Entity Framework Skip/Take is very slow when number to skip is big
- Combine two list of decimals in one array