Entity Framework Core is slow or Blind Engineers

Published: (January 4, 2026 at 04:06 PM EST)
2 min read
Source: Dev.to

Source: Dev.to

Entity Framework Core is one of the most productive tools in the .NET ecosystem.
It allows teams to move fast, model domains cleanly, and ship features quickly. You can write code without diving into the details of how the database works, which is both an advantage and a disadvantage.

EF Core works great — until the project grows.

  • More data
  • More relations
  • More edge cases
  • More performance‑sensitive paths

At that point, problems start appearing and EF often gets blamed. Engineers may add additional indexes, which only temporarily masks the issue.

Root cause: engineers have no idea how an EF query is converted into SQL.

In many mature codebases, LINQ queries are written without any consideration for how they translate to SQL. At a small scale this often goes unnoticed:

  • Few records
  • Low concurrency
  • Acceptable latency

But as data grows, those “innocent” queries can turn into:

  • Unexpected multiple joins
  • N+1 queries
  • Full table scans
  • Excessive memory usage
  • Unoptimized execution plans

EF Core doesn’t hide SQL — it generates it. If you don’t understand the generated SQL, you are effectively coding blind.

A Real Example from Production

A few years ago, while investigating performance issues in a production system, I found legacy code that:

  1. Loaded a few hundred entities into memory
  2. Enabled change tracking
  3. Updated them in a loop
  4. Called SaveChangesAsync()
var cutoff = nowUtc.AddDays(-90);

var users = await db.Users
    .Where(u =>
        u.Status == UserStatus.Active &&
        (u.LastLoginUtc == null || u.LastLoginUtc 
        u.Status == UserStatus.Active &&
        (u.LastLoginUtc == null || u.LastLoginUtc  setters
        .SetProperty(u => u.Status, UserStatus.Archived)
        .SetProperty(u => u.UpdatedAtUtc, nowUtc),
        ct);

The root cause was not “EF is slow”. It was using an ORM abstraction without understanding its cost.

Takeaways

  • Understand how LINQ translates to SQL.
  • Know when change tracking is needed—and when it isn’t.
  • Recognize when a query should be set‑based, compiled, or written as raw SQL.
  • Use the right tool for the job: sometimes EF Core is ideal; other times a stored procedure, view, or raw query is a better fit.

Do not blame the tool if you do not understand how it works.

Back to Blog

Related posts

Read more »

C# Smart Enums: advanced

!Cover image for C Smart Enums: advancedhttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-upload...