SALE! All courses are on the lowest price! Enroll Now
Entity Framework

LINQ Mistakes Everyone Makes

Bhrugen Patel

Bhrugen Patel

Author

Published
March 11, 2026
10 min read
1 views
Discover common mistakes developers make when using LINQ in C#. Learn how to avoid these pitfalls and write efficient, maintainable LINQ queries.
Share this article:

LINQ Mistakes Everyone Makes (And How to Fix Them)

LINQ is awesome. It makes querying data feel natural and readable. But I see the same mistakes in almost every code review I do. And honestly? I've made all of these myself at some point.

Let me show you the most common LINQ mistakes and how to avoid them. Some of these can absolutely tank your app's performance.

Mistake #1: Enumerating Multiple Times

This is probably the #1 mistake I see. Check this out:

var users = _context.Users.Where(u => u.IsActive);

// Executing query 1
var count = users.Count();

// Executing query 2 
var firstUser = users.FirstOrDefault();

// Executing query 3
foreach (var user in users)
{
    Console.WriteLine(user.Name);
}

❌ What's Wrong Here?

You just hit the database THREE times for the same data! Each time you enumerate (Count, FirstOrDefault, foreach), LINQ executes the query again.

The fix? Just call ToList() once:

var users = _context.Users
    .Where(u => u.IsActive)
    .ToList(); // Execute once, store in memory

var count = users.Count();        // In-memory
var firstUser = users.FirstOrDefault(); // In-memory
foreach (var user in users)       // In-memory
{
    Console.WriteLine(user.Name);
}

✅ Much Better

One database query. Everything else happens in memory. Your database will thank you.

Mistake #2: Using Count() When You Mean Any()

I see this one everywhere:

if (_context.Users.Count() > 0)
{
    // Do something
}

if (_context.Orders.Where(o => o.UserId == userId).Count() > 0)
{
    // User has orders
}

❌ Why This Hurts

Count() has to count EVERY SINGLE ROW. If you have a million users, it counts all million just to tell you "yep, more than zero."

Use Any() instead:

if (_context.Users.Any())
{
    // Do something
}

if (_context.Orders.Any(o => o.UserId == userId))
{
    // User has orders
}

✅ Way Faster

Any() stops as soon as it finds one match. It's like the difference between "check if there's milk in the fridge" vs "count every milk carton in the store."

Performance Comparison

Rows in Table Count() > 0 Any()
1,000 ~50ms ~2ms
100,000 ~500ms ~2ms
1,000,000 ~5000ms ~2ms

Mistake #3: Loading Everything When You Need Two Fields

This kills performance in so many apps:

var users = _context.Users.ToList();

foreach (var user in users)
{
    Console.WriteLine($"{user.FirstName} {user.LastName}");
}

❌ You're Wasting Memory

You need two fields (FirstName, LastName) but you're loading the entire User object - email, password hash, profile pic, created date, modified date, settings, preferences... all of it!

Use Select to get only what you need:

var users = _context.Users
    .Select(u => new 
    {
        u.FirstName,
        u.LastName
    })
    .ToList();

foreach (var user in users)
{
    Console.WriteLine($"{user.FirstName} {user.LastName}");
}

✅ Much Lighter

The SQL query only selects FirstName and LastName. Less data over the wire, less memory used, faster query.

Pro tip: If you have 10,000 users and each User object is 5KB, you just saved 50MB of memory.

Mistake #4: Where() Then FirstOrDefault()

This one's subtle but I see it all the time:

var user = _context.Users
    .Where(u => u.Id == userId)
    .FirstOrDefault();

It works, but you can simplify it:

var user = _context.Users
    .FirstOrDefault(u => u.Id == userId);

💡 Why It's Better

Same SQL, less code. FirstOrDefault, SingleOrDefault, and Last all accept predicates. You don't need the separate Where().

Other examples:

  • Any(x => x.IsActive) not Where(x => x.IsActive).Any()
  • Count(x => x.IsActive) not Where(x => x.IsActive).Count()
  • Single(x => x.Id == 5) not Where(x => x.Id == 5).Single()

Mistake #5: Calling ToList() Too Early

This is the opposite problem - calling ToList() before you're done building the query:

var users = _context.Users
    .Where(u => u.IsActive)
    .ToList(); // Too early!

// Now filtering in memory instead of database
var admins = users
    .Where(u => u.Role == "Admin")
    .ToList();

❌ What Just Happened?

You loaded ALL active users into memory, then filtered for admins in C#. If you have 100,000 active users but only 5 admins, you just wasted a ton of memory and bandwidth.

Keep it as IQueryable until the end:

var admins = _context.Users
    .Where(u => u.IsActive)
    .Where(u => u.Role == "Admin")
    .ToList(); // Now it's all in one SQL query

✅ Database Does the Work

Both Where clauses get combined into one SQL query. Database returns only the 5 admins. Way more efficient.

⚡ The Rule

Call ToList() as late as possible. Let the database do the filtering, sorting, and joining. That's what it's good at.

Mistake #6: The N+1 Query Problem

This is the classic. Probably the worst performance killer in LINQ:

var users = _context.Users.ToList();

foreach (var user in users)
{
    // Hitting database for EACH user!
    var orders = _context.Orders
        .Where(o => o.UserId == user.Id)
        .ToList();
    
    Console.WriteLine($"{user.Name} has {orders.Count} orders");
}

❌ Performance Killer

If you have 100 users, you just made 101 database queries (1 for users + 100 for orders). This is called the N+1 problem and it will destroy your app's performance.

Use Include() or a join:

// Option 1: Include
var users = _context.Users
    .Include(u => u.Orders)
    .ToList();

foreach (var user in users)
{
    Console.WriteLine($"{user.Name} has {user.Orders.Count} orders");
}

// Option 2: Join with grouping
var userOrders = _context.Users
    .Select(u => new
    {
        u.Name,
        OrderCount = u.Orders.Count
    })
    .ToList();

foreach (var item in userOrders)
{
    Console.WriteLine($"{item.Name} has {item.OrderCount} orders");
}

✅ One Query

Both options generate a single SQL query with a JOIN. Instead of 101 queries, you get 1. That's like 100x faster.

Mistake #7: OrderBy Before Take/First

Sometimes the order matters. Look at this:

// Wrong order - sorts everything first
var user = _context.Users
    .Where(u => u.IsActive)
    .OrderBy(u => u.Name)
    .FirstOrDefault();

vs

// Better - filter first, then sort
var user = _context.Users
    .Where(u => u.IsActive)
    .Where(u => u.Role == "Admin")
    .OrderBy(u => u.Name)
    .FirstOrDefault();

💡 Why Order Matters

Narrow down your results with Where() first, THEN sort. Don't sort 1 million rows when you only need to sort 100.

Mistake #8: Complex Operations in Where Clauses

LINQ to SQL can't translate everything to SQL. This will bite you:

var users = _context.Users
    .Where(u => u.FirstName.ToUpper() + " " + u.LastName.ToUpper() == searchTerm)
    .ToList();

❌ This Might Not Work

Depending on your EF Core version, this could either throw an exception or (worse) execute in memory after loading all users.

Keep your Where clauses simple:

var users = _context.Users
    .Where(u => u.FirstName.Contains(searchTerm) || 
                u.LastName.Contains(searchTerm))
    .ToList();

// Or do complex stuff after ToList()
var users = _context.Users
    .Where(u => u.IsActive)
    .ToList()
    .Where(u => (u.FirstName + " " + u.LastName).ToUpper() == searchTerm)
    .ToList();

⚡ What Can't Be Translated?

  • Custom methods (unless they're mapped)
  • Complex string concatenations
  • DateTime operations beyond basic comparisons
  • Calling external APIs or services

The Bottom Line

LINQ is powerful, but it's easy to write code that looks fine but performs terribly. I've made every single one of these mistakes. Some of them multiple times.

⚡ Quick Reference:

  • Call ToList() once if you'll enumerate multiple times
  • Use Any() instead of Count() > 0
  • Use Select() to load only what you need
  • FirstOrDefault(predicate) instead of Where().FirstOrDefault()
  • Call ToList() as late as possible
  • Watch out for N+1 queries - use Include() or joins
  • Filter with Where() before OrderBy()
  • Keep Where clauses simple - database can't run your C# code

Look, your code doesn't have to be perfect. But knowing these common mistakes will save you from some really painful debugging sessions when your app starts slowing down in production.

💡 Pro Tip

Use a SQL profiler or logging to see what queries EF Core generates. You'll be surprised what some innocent-looking LINQ turns into.

Now go fix those queries! Your future self (and your database) will thank you.

Tags:

Bhrugen Patel

About Bhrugen Patel

Expert .NET developer and educator with years of experience in building real-world applications and teaching developers around the world.

Related Articles