In this lesson, you will learn how to distinguish between LINQ queries executed directly on your database and those forced into local memory.
When you write a LINQ query against a DbSet<T>, Entity Framework Core attempts to translate your C# code into a SQL query. This is called LINQ-to-Entities translation. The goal is for the database to perform the heavy lifting—filtering, sorting, and aggregating data—before the results are sent to your application.
The Translation Boundary
EF Core can only translate LINQ methods that have a direct SQL equivalent. Methods like Where(), Select(), OrderBy(), Take(), and Join() are perfectly translated into SQL keywords like WHERE, SELECT, ORDER BY, LIMIT, and JOIN.
However, once you call a method that EF Core cannot translate (or you call .ToList() or .AsEnumerable()), the query execution shifts from the database to your application’s memory (Client-Side Evaluation).
Consider this example:
// This is translated to SQL:
// SELECT * FROM Posts WHERE Title LIKE '%EF Core%'
var query = context.Posts
.Where(p => p.Title.Contains("EF Core"));
// By calling ToList(), we force the transition:
var data = query.ToList();
// If you try to call a custom C# method inside the query,
// EF Core may throw an exception or pull all rows into memory:
var problematic = context.Posts
.Where(p => MyCustomLocalMethod(p.Title))
.ToList();
Why it Matters
If you accidentally write a query that cannot be translated, EF Core will fetch every single row from your table into your application’s RAM to perform the filtering locally. For small tables, this is unnoticeable. For tables with thousands or millions of records, this leads to severe performance degradation and potential OutOfMemoryException errors.
To verify what is being sent to the database, always check your application logs; if you see a warning about "Client-side evaluation," it means your LINQ query has partially "leaked" out of the database engine and into your C# runtime.
Key Takeaway: Keep your LINQ queries within the bounds of database-compatible operations to ensure logic is executed as efficient SQL rather than expensive local memory processing.