← ClaudeAtlas

ef-core-query-reviewlisted

Review EF Core LINQ queries for N+1, cartesian explosion, tracking overhead, client-side evaluation, and over-fetching. Use when writing or reviewing any code that queries a DbContext.
Sarmkadan/dotnet-senior-skills · ★ 0 · Code & Development · score 72
Install: claude install-skill Sarmkadan/dotnet-senior-skills
# EF Core Query Review ## N+1: lazy loading and loops over navigations ```csharp // WRONG: 1 query for orders + N queries for customers var orders = await db.Orders.ToListAsync(); foreach (var o in orders) Console.WriteLine(o.Customer.Name); // lazy-load per row ``` Fix with a projection, not an Include, when you only need a few fields: ```csharp var rows = await db.Orders .Select(o => new { o.Id, CustomerName = o.Customer.Name }) .ToListAsync(); // single query, single roundtrip ``` If lazy-loading proxies are enabled project-wide, treat every navigation access outside the query as a suspect. Prefer disabling lazy loading entirely; it converts silent N+1 into a visible exception. ## Cartesian explosion with multiple collection Includes ```csharp // WRONG: rows = orders x items x payments; 100 orders with 50 items and 10 payments = 50,000 rows var o = await db.Orders.Include(x => x.Items).Include(x => x.Payments).ToListAsync(); ``` Two or more collection `Include`s on the same level multiply row counts. Use `AsSplitQuery()` (one query per collection, consistent only inside a transaction or with snapshot isolation) or split into separate targeted queries. One collection Include is fine; two is a review comment; three is a rejection. ## Projection over materialization Materializing full entities to return a DTO is the most common over-fetch. `Select` into the DTO directly: EF translates it to a column list, skips change tracking, and avoids loading unmapped bl