question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Query performance: Client evaluation for tracked queries returning an entity by key

See original GitHub issue

Currently a query like this will always cause a database round trip:

var product = context.Products.FirstOrDefault(p => p.Id == pid);

As mentioned in the comments of #797 we have been talking for some time about handling such queries differently: we can check first if an entity exists in the context that matches the predicate, and if found we can short-circuit the database query.

In terms of previous versions of EF this would be equivalent or very similar to DbSet<T>.Find() and ObjectContext.GetObjectByKey()` (the main difference between these two is that the latter cannot be used to retrieve objects in the added state).

Initially we could support only queries that:

  1. Return a tracked entity
  2. Do not use Include()
  3. Are restricted by a simple predicate of the general form entityKey == value
  4. Have that predicate passed to First(), FirstOrDefault(), Single() or SingleOrDefault()

Then (also initially or in the longer term) we can pick other scenarios in which the database query can be unnecessary, e.g.:

// Deferred query that return a single entity is compelling as many customers will use it
var product1 = context.Products.Where(p => p.Id == pid).First();
// Composite predicates
var product2 = context.Products.First(p => p.Id == pid && !string.IsNullOrEmpty(p.Name));
// Any() over a predicate by key could sometimes return true without going to the database
var found = context.Products.Any(p => p.Id == pid);
// Contradictions don't need round tripping, but are less common 
var never = context.Products.Where(p => p.Presentation != p.Presentation);

The only observable functional change I can think of is with entities that have been deleted in the database after the entity was originally retrieved in the context. Previously the query would not return the entity, although the entity would continue to be present in the context. This change in fact makes the behavior more consistent with the snapshot semantics of the DbContext, although only for a (very useful) subset of the queries.

Note also that this is a popular feature in LINQ to SQL.

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
ajcvickerscommented, Nov 18, 2019

Closing old issue as this is no longer something we intend to implement.

0reactions
stevendarbycommented, Sep 12, 2019

What would be nice is if there was a DbSet<T>.Find overload that took an instance of T and did the matching on the primary key. It also means you can use it from generic methods where you have an entity but don’t know its properties at compile time.

A use case for this is that the input entity may have been constructed in code and might only have its primary key set.

It also means Find is more strongly typed, as you’re passing in the primary key value(s) via the types properties and not just as a params array of objects.

I appreciate there may be workarounds for some of the use cases I mentioned (perhaps querying Local then FirstOrDefault for object equivalence, or using the entity metadata to get the primary key value(s)?) but abstracting this process into a neat Find seems like a good idea, to me at least. I didn’t see this suggestion here so thought I’d mention it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Tracking vs. No-Tracking Queries - EF Core
By default, queries that return entity types are tracking. A tracking query means any changes to entity instances are persisted by ...
Read more >
Chapter 4. Query Performance Optimization
We show you how to find out how MySQL executes a particular query, and you'll learn how to change the query execution plan....
Read more >
Use Query insights to improve query performance
Query insights helps you improve Cloud SQL query performance by guiding you through the following steps: View the database load for top queries....
Read more >
How to collect performance and system information in SQL ...
In this article, we're going through many of the tools we can use for monitoring SQL Server performance to quickly spot whether there...
Read more >
Entity-framework code is slow when using Include() many ...
Tracking creates proxies, and EF logic for creating proxies significantly slows down performance. If it's still slow, and your database is SQL ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found