If I have such code in Entity Framework
var data = query.AsEnumerable().Where(x => IsObjectValid(x)).ToList()
where query is IQueryable that can be translated to SQL.
Will Entity Framework load all the entries from the database in-memory (just as ToList() would do) and then apply the IsObjectValid() function and filter the data. Or Entity Framework will load entries from the database one by one and apply the filtration function?
If I have 1000 entries in query, where each weighs 1 MB, will the memory usage be the same for ToList().Where() and for AsEnumerable().Where()?
In my tests .AsEnumerable() worked faster and consumed way less memory.
Thanks!
The part before
AsEnumerable()will be translated to SQL and performed by the DB. The part afterAsEnumerable()will be performed as LINQ to Objects after the data has been loaded from the DB.The first
Wherewill be performed on the DB and only the records withAuthor = "me"will be returned to your application. The secondWherewill then be performed on this returned data and theToList()on the data filtered twice.Custom functions cannot be translated to SQL. Therefore,
AsEnumerable()is required to be able to call this function locally. But it is advisable to do as much of a filtering and grouping, etc. beforeAsEnumerable()to minimize the returned data.The first
Whereexpects anExpression<Func<T, bool>>parameter, where as the second one expects aFunc<T, bool>parameter. I.e.,AsEnumerable()transitions fromIQueryable<T>toIEnumerable<T>.An
Expression<Func<T, bool>>consists of a data structure representing the syntax of the lambda function. This syntax is translated to an equivalent SQL syntax. This also means that the lambda expressions used in IQueryables are actually never executed. Therefore, it does not matter whether you write e.g.Where(x => hasSet.Contains(x))orWhere(x => array.Contains(x))performance-wise. Both will be translated to something likeWHERE x IN (a, b, c). But it matters afterAsEnumerable().HashSet<T>.Containsis faster thanList<T>.ContainsorT[].Contains.As @DavidBrowne-Microsoft explains,
AsEnumerable()does a lazy evaluation over aDataReader. The following LINQ to Objects operations perform a lazy evaluation whenever possible. I.e., one data object is processed at a time and passed over to the next operation.Operations like
Where,Select,Skip,SkipWhileetc, perform a lazy evaluation. Other operations likeOrderBy,GroupByorReversemust keep all the data in memory.And of course
ToList,ToArrayandToDictionarypull all the data and store it in memory. I often see people append aToList()to a query just to do afororforeachon the result. Perform theforeachdirectly on theIEnumerable<T>result whenever possible! Often there is no need to store the whole data in memory.