---
title: "Improve the performance of a slow-running LINQ query"  
description: "Improving the performance of a slow-running LINQ query—especially when using Entity Framework or LINQ to SQL"  
author: "ICSM Computer"  
published: 2025-06-16  
updated: 2025-06-16  
canonical: https://www.mindstick.com/blog/305732/improve-the-performance-of-a-slow-running-linq-query  
category: "c#"  
tags: ["c#", "linq"]  
reading_time: 3 minutes  

---

# Improve the performance of a slow-running LINQ query

Improving the performance of a **slow-running [LINQ query](https://www.mindstick.com/forum/33908/how-to-select-and-retrieve-data-using-linq-query-in-entity-framework)**—especially when using [Entity Framework](https://www.mindstick.com/articles/1566/crud-operations-using-entity-framework-code-first-approach) or [LINQ to SQL](https://www.mindstick.com/articles/338528/how-to-use-linq-to-sql-select-query-using-c-sharp)—often requires identifying bottlenecks and applying optimizations both in **code** and at the **database level**.

## 1. Use `AsNoTracking()` for Read-Only Queries

Entity Framework by default tracks entities, which adds overhead. Use this for read-only queries:

```cs
var users = context.Users.AsNoTracking().Where(u => u.IsActive).ToList();
```

## 2. Filter Early (Apply `Where` as Soon as Possible)

Move `.Where()` clauses before any `.Select()`, `.ToList()`, `.Include()`, etc., to limit the dataset early:

```cs
// BAD: selects all before filtering
var data = db.Users.Select(u => new { u.Id, u.Name }).Where(u => u.Id > 100).ToList();

// GOOD: filters first
var data = db.Users.Where(u => u.Id > 100).Select(u => new { u.Id, u.Name }).ToList();
```

## 3. Avoid N+1 Problems with `.Include()`

Use `.Include()` to eagerly load [related data](https://www.mindstick.com/interview/22990/what-is-lazy-eager-and-explicit-loading-of-related-data-in-entity-frameworks) and avoid multiple queries:

```cs
// BAD: causes N+1 query problem
var users = context.Users.ToList();
foreach (var user in users) {
    var orders = context.Orders.Where(o => o.UserId == user.Id).ToList();
}

// GOOD: loads related data in one query
var users = context.Users.Include(u => u.Orders).ToList();
```

## 4. Project Early with `.Select()`

Avoid loading entire entities when you only need a few fields:

```cs
// BAD: loads all columns
var users = context.Users.ToList();

// GOOD: projects to lightweight objects
var users = context.Users.Select(u => new { u.Id, u.Name }).ToList();
```

## 5. Limit Results with `.Take()` / `.Skip()`

Only retrieve what you need:

```cs
var recentUsers = context.Users.OrderByDescending(u => u.CreatedDate).Take(50).ToList();
```

## 6. Use Indexes in the Database

Ensure [SQL Server](https://www.mindstick.com/articles/12999/what-is-table-valued-function-in-sql-server) (or other DB) has proper indexes on columns used in:

- `Where`
- `OrderBy`
- `Join` conditions

You can use `.ToQueryString()` in [EF Core](https://www.mindstick.com/forum/161362/what-is-ef-core-and-how-is-it-different-from-entity-framework-ef6) to inspect the SQL and identify [performance bottlenecks](https://www.mindstick.com/interview/34058/identifying-and-resolving-performance-bottlenecks).

## 7. Batch Queries (Avoid Large `ToList()` Calls)

If you’re processing a large dataset, use batching to [reduce memory](https://www.mindstick.com/interview/34250/what-are-some-strategies-to-reduce-memory-usage-in-high-load-dot-net-apps) pressure:

```cs
var pageSize = 100;
for (int i = 0; i < totalCount; i += pageSize)
{
    var batch = context.Users.Skip(i).Take(pageSize).ToList();
    Process(batch);
}
```

## 8. Avoid Client-Side Evaluation

Make sure your LINQ [expressions](https://www.mindstick.com/forum/33876/what-is-the-syntax-for-lambda-expressions-in-vb-dot-net) are fully translatable to SQL. Otherwise, EF will bring data into memory and evaluate it on the client (which is slow).

```cs
// BAD: Contains on a list of objects not supported in SQL
var ids = someComplexObjectList.Select(x => x.Id);
var data = context.Users.Where(u => ids.Contains(u.Id)).ToList(); // may run in memory

// GOOD: use a plain list of IDs
var idList = new List<int> { 1, 2, 3 };
var data = context.Users.Where(u => idList.Contains(u.Id)).ToList();
```

## 9. Profile the Generated SQL

Use:

- `.ToQueryString()` in EF Core
- [SQL Profiler](https://www.mindstick.com/forum/156787/what-is-sql-profiler-in-sql-server) or logs To inspect the actual SQL and optimize it.

```cs
var query = context.Users.Where(x => x.IsActive);
Console.WriteLine(query.ToQueryString());
```

## 10. Split Complex LINQ into Steps

Break large LINQ queries into smaller parts to help EF translate them better and isolate bottlenecks.

### Summary Table

| Strategy | Benefit |
| --- | --- |
| `AsNoTracking()` | No overhead from change tracking |
| Filter early (`Where`) | Reduces rows returned |
| `Select()` early | Avoids loading unnecessary data |
| Use `Include()` | Avoids N+1 query issue |
| Limit with `Take()` / `Skip()` | Improves performance on large sets |
| Proper DB indexing | Speeds up lookups and joins |
| Avoid client-side eval | Ensures optimal SQL generation |
| Query batching | Manages memory and performance |
| Profile SQL | Find real bottlenecks |

---

Original Source: https://www.mindstick.com/blog/305732/improve-the-performance-of-a-slow-running-linq-query

Copyright © MindStick Software Pvt. Ltd. This Markdown version is provided for developers, AI systems, and offline reading.
