LINQ provides the query expression used to read Entity Framework Core data from an ASP.NET Core endpoint. The endpoint receives a database context through dependency injection, queries a DbSet<T>, and uses the returned model object to prepare its response. Entity Framework Core translates the query into SQL and sends it to the database. section 17.5.6 section 17.6
Look up a stored calculation
A sum endpoint reads its route value and searches stored calculations with `dataContext.Calculations?.FirstOrDefault(c => c.Count == count)?.Result ?? 0`. If it finds no stored result, it performs the calculation, adds a model object, and calls `SaveChangesAsync()`. Requesting `/sum/10` retrieves a seeded result; requesting `/sum/100` calculates and stores a missing one. A later request for that URL can use the stored result, but it still issues a query. section 17.5.6
...
Executing DbCommand [Parameters=[@__count_0='?' (DbType = Int32)],
CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [c].[Id], [c].[Count], [c].[Result]
FROM [Calculations] AS [c]
WHERE [c].[Count] = @__count_0
...
The logged command shows the `FirstOrDefault` lookup as `SELECT TOP(1)` with a parameterized `WHERE` clause. Inspect the SQL, not just the LINQ expression, when judging what the database does. section 17.5.6 section 17.5
LINQ is not a promise that every operation becomes efficient SQL. Not all LINQ features can be translated into SQL, and a query can retrieve far more data than the application ultimately uses. Poor Entity Framework Core performance often calls for examining the generated SQL rather than treating the framework as a black box; doing that well requires SQL knowledge. section 17.5
A LINQ expression exposed through an `IEnumerable<T>` property can represent a query rather than a saved set of results. Reading the property again can send another database query. In a Blazor list, `Count()` and `@foreach` each read the property; an unrelated button click rerenders the component and repeats both reads. Watch for duplicate commands before assuming the button itself performs data operations. section 36.3.2
... info: Microsoft.EntityFrameworkCore.Database.Command[20101] Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT [p].[PersonId], [p].[DepartmentId], [p].[Firstname], [p].[LocationId], [p].[Surname], [d].[Departmentid], [d].[Name], [l].[LocationId], [l].[City], [l].[State] FROM [People] AS [p] INNER JOIN [Departments] AS [d] ON [p].[DepartmentId] = [d].[Departmentid] INNER JOIN [Locations] AS [l] ON [p].[LocationId] = [l].[LocationId] info: Microsoft.EntityFrameworkCore.Database.Command[20101] Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT [p].[PersonId], [p].[DepartmentId], [p].[Firstname], [p].[LocationId], [p].[Surname], [d].[Departmentid], [d].[Name], [l].[LocationId], [l].[City], [l].[State] FROM [People] AS [p] INNER JOIN [Departments] AS [d] ON [p].[DepartmentId] = [d].[Departmentid] INNER JOIN [Locations] AS [l] ON [p].[LocationId] = [l].[LocationId] ...
The command log shows two identical SELECT statements from a single component render, making the repeated-query cost visible. section 36.3.2


