Rule Definition
The DbSet class is derived from IQuerayable. So, we can use LINQ for querying against DbSet, which will be converted to an SQL query. EF API executes this SQL query to the underlying database, gets the flat result set, converts it into appropriate entity objects and returns it as a query result.
Calling ToList()/ToArray() on IEnumerable creates a new list/array and populates it with all items of the data set, thereby executing the LINQ query associated to the IEnumerable object and performing a “full scan”. IEnumerable has been built to work seamlessly with “foreach” loops and calling ToList()/ToArray() should be avoided to save memory and CPU.
Remediation
Do not materialize the full result set in memory unless absolutely required.
Instead, prefer lazy iteration (foreach over IQueryable) or use asynchronous streaming via .AsAsyncEnumerable() when dealing with Entity Framework Core.
Remediation Steps:
- Remove .ToList(), .ToArray(), or .ToDictionary() if you don’t need to manipulate the entire dataset in memory.
- Use await foreach with .AsAsyncEnumerable() in async contexts for better scalability.
- If filtering or sorting is needed, apply it at the query level using LINQ before the iteration.
Violation Code Sample
using (var context = new ApplicationDbContext ())
{
foreach(var student in context.Students.ToList()) // ⚠️ VIOLATION
{
...
}
foreach(var student in context.Students.ToArray()) // ⚠️ VIOLATION
{
...
}
foreach(var student in context.Students.ToDictionary (x => x.Id)) // ⚠️ VIOLATION
{
...
}
}
Fixed Code Sample
# Preferred
await foreach (var item in dbContext.Users.AsAsyncEnumerable())
{
Console.WriteLine(item.Name); // ✓ FIXED
}
# Preferred synchronous context is acceptable and dataset is small
foreach (var item in dbContext.Users)
{
Console.WriteLine(item.Name); // ✓ FIXED
}
# if you really need the converted data
var studentsList = context.Students.ToList ();
foreach(var student in studentsList) // ✓ FIXED
{
...
}
Reference
https://learn.microsoft.com/en-us/ef/core/querying/client-eval#avoiding-premature-query-execution
https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.entityframeworkqueryableextensions.asasyncenumerable
https://learn.microsoft.com/en-us/ef/core/performance/
Related Technologies
Technical Criterion
CWE-1050 - Excessive Platform Resource Consumption within a Loop [Base]
About CAST Appmarq
CAST Appmarq is by far the biggest repository of data about real IT systems. It's built on thousands of analyzed applications, made of 35 different technologies, by over 300 business organizations across major verticals. It provides IT Leaders with factual key analytics to let them know if their applications are on track.