COMPUTER ENGINEER

Jump to examples
Blog
Next.js / ASP.NET Core / SQL6 min study
27/ 41

Data layer and SQL

From LINQ to SQL: how EF Core translates a query

Which part runs in the database, which in memory, and how to read the generated SQL.

UnderstandStudy an examplePractise

Understand the concept

A LINQ query you write in EF Core does not run immediately; it accumulates as an expression tree. When a terminating operator such as ToListAsync, SingleAsync or CountAsync is called, EF Core translates the tree into SQL, adds parameters and sends it to the database. Where, OrderBy, Select and Take become SQL and run in the database.

Projecting with Select fetches only the needed columns. Loading whole entities and using a few fields in memory moves needless data over the network, which matters a lot for large text columns. DTOs created by projection are not tracked; this is the most efficient path for read endpoints.

If an untranslatable expression (for example your own C# method) is used inside Where, EF Core throws rather than silently pulling the query into memory and filtering there. To see the generated SQL use ToQueryString() or EF Core logging in development. Making a habit of reading the SQL catches performance problems before production.

WHEN TO USE IT

Two LINQ queries with the same result can produce very different SQL and cost.

COMMON PITFALL

Calling ToList() early and doing filtering and paging in memory.

LIVE ANIMATION

A letter’s journey through the city

Think of a request as a letter and the server as a city. Pick a scenario, press play and watch which gates the letter passes and where it gets stopped.

CLIENTEDGEWEB SERVERAPI · ASP.NET COREDATABrowserThe user’s screenNetworkDNS · TCP · TLSReverse proxyTLS termination, compressionNext.js serverSSR and route handlersKestrelHTTP serverException handlerMiddlewareRoutingEndpoint selectionRate limiterMiddlewareAuthenticationWho you areAuthorizationWhat you may doModel bindingHTTP → C# + validationControllerEndpoint codeServiceBusiness rules (DI)RedisDistributed cacheEF CoreLINQ → SQLSQL ServerQuery plan, indexes
OUTBOUND →

You clicked a post. The browser writes a letter saying ‘send me this post’.

BrowserYour screen. It writes the request and finally turns the answer into a page.
1 / 22
01 / PRACTICE

One topic. Three levels of depth.

Illustrative example
var titles = await db.Posts
    .Where(p => p.IsPublished)
    .OrderByDescending(p => p.PublishedAtUtc)
    .Select(p => p.Title)
    .Take(5)
    .ToListAsync(ct);
// SELECT TOP(@p) [p].[Title] FROM [Posts] AS [p]
// WHERE [p].[IsPublished] = 1 ORDER BY [p].[PublishedAtUtc] DESC

The whole chain becomes one SQL query that runs in the database.

This page connects to no real server or database. Code samples are illustrative for .NET 8, Next.js and SQL Server; timings are example values in the simulation, not measurements. Try samples only in your own development environment; never share real connection strings, tokens or passwords.

02 / YOUR TURN

Try it yourself first.

The list page shows only title and date, but the query also loads the Content column (about 40 KB on average). How much needless data moves for a 20-post page, and how do you fix it?

Show the solution and explanation
Worked solution
≈ 20 × 40 KB = 800 KB gereksiz veri (her sayfa açılışında).
Düzeltme: .Select(p => new PostListItem(p.Title, p.PublishedAtUtc))

Projection narrows the SQL SELECT list; database, network and memory load drop together.