October DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PCOctober DealsAmazon USDeal season is back - check today's better picksAmazon US: current deals, useful picks and tech finds.See Picks×
Skip to content
World desk8 min

Entity Framework Core Performance Optimization: A Practical Guide for .NET Developers

Find the real EF Core bottleneck before changing code. Learn how to inspect SQL, reduce query work, optimize updates, and evaluate compiled queries and context pooling.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To improve Entity Framework Core performance, first find the slow part of a representative operation. Then inspect its generated SQL and database execution plan before changing the LINQ or EF Core configuration. In many applications, database work, network latency, or unnecessary data transfer costs more than EF Core’s own runtime overhead.

Work from the largest measured cost downward: check indexes and roundtrips, return only the data you need, bound large result sets, and choose tracking and relationship-loading behavior to match the workload. Consider compiled queries, context pooling, and model changes only when a benchmark shows they address a remaining bottleneck.

As an Amazon Associate I earn from qualifying purchases.

How do you find the real EF Core bottleneck?

Start with a slow request or operation you can reproduce using data and conditions close to production. Capture EF Core command logs and timings for a short diagnostic interval. Look for slow SQL, repeated commands, unexpectedly large result sets, and time spent outside database calls. Logging adds overhead and can consume disk space, so it is a diagnostic aid—not something to enable indiscriminately in production.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Connect SQL commands to the LINQ call site

Query tags can label a query so its SQL is easier to associate with the code that issued it:

var posts = await context.Posts
    .TagWith("Recent posts for dashboard")
    .Where(post => post.IsPublished)
    .ToListAsync();

Use the database’s own performance tools to inspect the actual execution plan and index use. A plan that looks acceptable with a small development dataset may change with production-scale data or different value distributions.

Measure EF-specific behavior and compare fairly

EF Core metrics can help identify issues such as query-cache behavior or contexts that are not being disposed. When comparing code paths, benchmark representative data and include the work the application actually performs. Microsoft recommends BenchmarkDotNet for controlled benchmarks, while cautioning that simple single-thread measurements do not replace concurrent-load testing.

Microsoft’s Performance Diagnosis guidance makes the key point: “It’s important to carefully diagnose and investigate any problems before jumping to any conclusions, and to avoid assuming where the root of the issue is.”

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How can you make queries do less database and network work?

Check indexes and execution plans first

Inspect whether the database can use appropriate indexes for the query’s filters and ordering. The LINQ expression alone does not tell you which access path the database will choose. Microsoft’s Efficient Querying guidance illustrates the difference with SQL Server: a StartsWith filter can use an index in its example, while EndsWith cannot. The result depends on the database provider and query shape.

Index design has trade-offs: indexes can accelerate reads but add work to updates. Composite-index order matters, too. An index on (A, B) can support filters on both columns and often on A alone, but not a filter on B alone. Applying an expression to a column can also prevent a simple index from being used; depending on the provider, a persisted computed column or expression index may help.

Microsoft summarizes the priority this way: “The main deciding factor in whether a query runs fast or not is whether it will properly utilize indexes where appropriate.” Verify that against the actual plan, and avoid adding indexes without considering their write cost.

Project only the fields the caller needs

If a page needs a title and date, select those values rather than loading full entity instances with every mapped column. A projection to an anonymous type or DTO reduces data materialized and transferred:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
var cards = await context.Posts
    .Where(post => post.IsPublished)
    .Select(post => new PostCard(post.Title, post.PublishedAt))
    .ToListAsync();

This is especially straightforward for read-only work. EF Core change tracking applies to entity instances; if the operation must modify entities and rely on change detection, choose a query shape that supports that requirement.

Put a deliberate bound on result sizes

Returning every matching row can increase database work, network transfer, memory use, and downstream processing. Apply a limit when the use case only needs a bounded result, and paginate when users need to navigate a larger set.

Skip/Take pagination is intuitive, but deep pages can become inefficient. For sequential navigation, keyset pagination is often a better fit. The right choice depends on how users move through the data and on provider behavior.

When should you change tracking or relationship loading?

Choose tracking based on what happens after the read

For read-only entity queries, AsNoTracking avoids the work of maintaining change-tracking state. Use tracking when the context needs to detect modifications to loaded entities. If a no-tracking result includes repeated references to the same entity and duplicate instances are undesirable, no-tracking with identity resolution is a possible middle ground.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Balance joins against extra roundtrips

Loading several related collections in one query can multiply rows and repeat parent data through join expansion, sometimes called cartesian explosion. Split queries can reduce that duplication, but may add roundtrips. Eager loading can be preferable when related data is known to be needed, because lazy loading may issue repeated roundtrips as navigation properties are accessed. Compare the generated SQL, row counts, and roundtrips for the real usage pattern rather than treating one loading strategy as universally best.

Should you buffer, stream, use async, or write raw SQL?

Buffer or stream according to result size and consumption

Methods such as ToListAsync buffer results, retaining them in memory. Async enumeration can stream a large result set so memory use stays bounded, although the application still has to process every row it consumes. Choose based on whether the caller needs the whole result at once or can act incrementally.

Use asynchronous database APIs consistently

Async database calls let scalable applications avoid blocking a thread while waiting for I/O. Avoid accidental mixing of synchronous and asynchronous database operations. Microsoft documents known async issues in Microsoft.Data.SqlClient for some scenarios, particularly large text or binary values; if async is unexpectedly slower, investigate the exact driver and version in use.

Reserve raw SQL for cases that justify the maintenance cost

Raw SQL can express provider-specific constructs that EF Core cannot translate, but it creates another query form to maintain. Check the SQL EF Core already generates first. Microsoft frames raw SQL as a last resort after inspecting generated SQL and establishing that the alternative solves a real performance need.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How can you make updates more efficient?

Understand SaveChanges batching for your provider

EF Core can batch multiple statements from SaveChanges into fewer roundtrips, but batching behavior depends on the provider. In Microsoft’s SQL Server guidance, batching tends to be less efficient below four statements and its benefits degrade after about 40; the cited SQL Server default maximum batch size is 42. These are SQL Server-specific figures, not universal settings. Benchmark before adjusting batch thresholds.

Use set-based updates for uniform changes

ExecuteUpdateAsync and ExecuteDeleteAsync, available starting with EF Core 7.0, can update or delete many rows in a single SQL statement without loading every entity or running change tracking for the operation. That changes the execution model: plan transaction boundaries and concurrency behavior, and account for any entities already tracked by the context that may become stale.

When are compiled queries and context pooling worth trying?

EF Core’s own runtime overhead is often less important than query efficiency, indexes, roundtrips, database I/O, and network latency. First fix those costs. If measurements still show significant EF-side overhead in a hot path, compiled queries or context pooling may be worth benchmarking.

Compiled queries target repeated query shapes

EF Core caches query compilation by expression-tree shape. Parameterize changing values so structurally identical queries can reuse compiled results; dynamically embedding changing constants can create cache misses and distinct SQL. Compiled queries bypass cache lookup for selected hot query shapes, but they require a single EF model and simple scalar parameters.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Microsoft’s sample benchmark reports the following compiled versus non-compiled query times. These are measurements from that sample, not expected results for another application:

Sample case Compiled Not compiled
One blog 564.2 μs 671.6 μs
Ten blogs 645.3 μs 709.8 μs

Context pooling targets context setup overhead

DbContext pooling reuses initialized contexts and is separate from database connection pooling. In Microsoft’s single-threaded benchmark fetching one row from a local SQL Server database, the sample reports these results:

Configuration Time Allocated memory
Without context pooling 701.6 μs 50.38 KB
With context pooling 350.1 μs 4.63 KB

That benchmark is a specific local, single-threaded scenario. Microsoft cautions that results vary with row count, network latency, and contention. A pooled context is reused across scopes, and OnConfiguring runs only when the context is initially created. Do not put per-request or tenant-varying state there; take care with pool sizing and state reset.

Do not disable safety checks without evidence

Disabling EF Core thread-safety checks is a further runtime optimization, not a remedy for concurrent use of a DbContext. Concurrent use is unsupported, and removing checks can hide concurrency bugs. Microsoft advises doing so only after thorough testing for those bugs.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Can model design affect EF Core query performance?

Denormalization and cached aggregates exchange query work for consistency work

Denormalization and cached aggregate values can reduce joins or repeated calculations, but they add synchronization obligations. A stored computed column suits a value derived from columns in the same row. A cached value dependent on other rows needs a reliable update mechanism. Database triggers can update values in the same transaction and avoid extra application roundtrips, although EF Core has no dedicated trigger-authoring API. Materialized or indexed views cache query results, with refresh and update behavior varying by database.

Inheritance mapping changes the query shape

Table-per-hierarchy (TPH) keeps a hierarchy in one table; table-per-type (TPT) splits types across tables and may require joins; table-per-concrete-type (TPC) uses tables for concrete types. Microsoft’s 2023 sample benchmark loaded all rows in a seven-type hierarchy with 5,000 rows per type (35,000 total):

Mapping Microsoft sample benchmark
TPH 149.0 ms
TPT 312.9 ms
TPC 158.2 ms

Those figures describe that particular hierarchy and query. Actual results depend on the query and the number of hierarchy tables, so they are not a blanket ranking for every model.

What does the measured cost of materializing data look like?

Microsoft’s 2022 diagnosis sample compared ways of averaging blog rankings. The results illustrate why calculating an aggregate in the database or reducing materialization can be worth testing; they are sample timings, not predictions for another workload.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Approach Microsoft 2022 sample result
Load tracked entities 2,860.4 μs
Load no-tracking entities 1,353.0 μs
Project only the ranking 910.9 μs
Calculate the average in the database 627.1 μs

What order should you use when optimizing?

  1. Reproduce and measure: capture timings for a representative slow operation and separate database time from application work.
  2. Inspect commands and plans: identify repeated roundtrips, transferred row and column volume, and whether appropriate indexes are used.
  3. Reduce query work: project only required data, bound results, choose pagination deliberately, and select relationship-loading behavior to fit the access pattern.
  4. Match tracking and writes to the workload: use no-tracking for suitable read-only entity queries, and evaluate set-based operations for uniform bulk changes.
  5. Benchmark remaining overhead: compare alternatives on production-like data, then consider compiled queries, context pooling, or model changes if measurements point to them.
  6. Validate under concurrency: a single-thread benchmark does not reveal the behavior of a concurrent production workload.

The benchmark figures and API guidance above come from Microsoft’s EF Core documentation, including Performance Diagnosis, Efficient Querying, efficient updating, advanced performance topics, and modeling performance. Provider behavior and EF Core version matter; verify version- and provider-specific details before applying them.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.