DEV Community

Cover image for EF Core Performance Tip: Use AsNoTrackingWithIdentityResolution for Read-Only Queries
Morteza Jangjoo
Morteza Jangjoo

Posted on • Originally published at jangjoo.hashnode.dev

EF Core Performance Tip: Use AsNoTrackingWithIdentityResolution for Read-Only Queries

In Entity Framework Core, when querying complex object graphs in read-only scenarios, one hidden performance gem is AsNoTrackingWithIdentityResolution(). It offers the speed benefits of AsNoTracking() while maintaining consistency by resolving repeated references to the same entity.

But what exactly does this method do, and when should you use it instead of AsNoTracking() or regular tracking? Let’s dive in.


🧠 What is AsNoTrackingWithIdentityResolution()?

EF Core uses a Change Tracker to keep track of all loaded entities by default. This is useful for updates, but can be unnecessary overhead when you're only reading data.

AsNoTracking() disables tracking, making queries faster and memory-efficient. However, when loading related entities (e.g., via .Include()), AsNoTracking() can return multiple instances of the same entity if it's referenced more than once.

That’s where AsNoTrackingWithIdentityResolution() comes in.

✅ It disables change tracking (like AsNoTracking()),

✅ But also resolves identity — ensuring only one instance per entity is created, even when referenced multiple times.


🔍 Example

Let’s say we have the following models:

public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public Author Author { get; set; }
}

public class Author
{
    public int Id { get; set; }
    public string Name { get; set; }
}
Enter fullscreen mode Exit fullscreen mode

Using AsNoTracking():

var posts = await _context.Posts
    .Include(p => p.Author)
    .AsNoTracking()
    .ToListAsync();
Enter fullscreen mode Exit fullscreen mode

In this case, if an author has written multiple posts, EF Core may return multiple Author instances with the same data — each one tied to a different Post.

Using AsNoTrackingWithIdentityResolution():

var posts = await _context.Posts
    .Include(p => p.Author)
    .AsNoTrackingWithIdentityResolution()
    .ToListAsync();
Enter fullscreen mode Exit fullscreen mode

Now, all posts written by the same author will reference the exact same Author object in memory — without enabling full tracking. Cleaner and more consistent.


📊 When to Use It

Scenario Recommendation
Simple read-only list (flat entities) Use AsNoTracking()
Complex graphs with reused references Use AsNoTrackingWithIdentityResolution()
You plan to modify and save entities Don't use either — use default tracking

💡 Performance Considerations

While AsNoTrackingWithIdentityResolution() is still faster than full tracking, it is slightly slower than plain AsNoTracking(), because it requires some internal caching to ensure identity resolution.

Method Tracking Identity Resolution Performance
Default ✅ Yes ✅ Yes 🚫 Slowest
AsNoTracking() ❌ No ❌ No ✅ Fastest
AsNoTrackingWithIdentityResolution() ❌ No ✅ Yes ⚡ In between

✅ Summary

AsNoTrackingWithIdentityResolution() strikes a great balance between performance and consistency when reading related data without needing tracking.

Use it when:

  • You load complex object graphs
  • You don’t plan to update the data
  • You want to avoid duplication in memory

Don’t use it if:

  • You’re updating entities (use full tracking instead)
  • You don’t need related entities or identity resolution (then AsNoTracking() is faster)

🧠 Final Thought

Knowing when to use tracking, AsNoTracking(), or AsNoTrackingWithIdentityResolution() is key to building fast and reliable EF Core applications. The right choice can save both memory and headaches — especially in high-traffic APIs or data-heavy dashboards.

I'm jangjoo and Happy querying! 🚀

Top comments (0)