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.

Multiple non-related dbset counts without filter executes as separate queries

See original GitHub issue

Including multiple non-related dbset counts in one query will perform multiple SQL queries if the dbsets are not filtered by a dummy where clause. AsSingleQuery does not help. I would prefer not having to remember to add the .Where(x => true) part to prevent multiple queries.

See full gist here.

Include your code

                // info: Microsoft.EntityFrameworkCore.Database.Command[20101]
                //     Executed DbCommand (4ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
                //     SELECT COUNT(*)
                //     FROM [Users] AS [u]
                // info: Microsoft.EntityFrameworkCore.Database.Command[20101]
                //     Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
                //     SELECT COUNT(*)
                //     FROM [Animals] AS [a]
                // info: Microsoft.EntityFrameworkCore.Database.Command[20101]
                //     Executed DbCommand (8ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
                //     SELECT TOP(1) 1
                //     FROM [Users] AS [u]

                var bad = await context.Users.Select(u => new {
                    userCount = context.Users.Count(),
                    animalCount = context.Animals.Count()
                }).FirstAsync();

                // info: Microsoft.EntityFrameworkCore.Database.Command[20101]
                //       Executed DbCommand (13ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
                //       SELECT TOP(1) (
                //           SELECT COUNT(*)
                //           FROM [Users] AS [u0]) AS [userCount], (
                //           SELECT COUNT(*)
                //           FROM [Animals] AS [a]) AS [animalCount]
                //       FROM [Users] AS [u]

                var good = await context.Users.Select(u => new {
                    userCount = context.Users.Where(x => true).Count(),
                    animalCount = context.Animals.Where(x => true).Count()
                }).FirstAsync();

Include provider and version information

EF Core version: 6.0.3 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET 6.0

Issue Analytics

  • State:open
  • Created a year ago
  • Comments:11 (10 by maintainers)

github_iconTop GitHub Comments

2reactions
rojicommented, Apr 5, 2022

Batching two SELECTs in a single roundtrip is likely to yield very similar performance to having the two selects as subqueries in a single SELECT query, i.e.:

SELECT COUNT(*) FROM [Users];
SELECT COUNT(*) FROM [Animals] AS [a];

… is very likely roughly equivalent to:

SELECT TOP(1) (
    SELECT COUNT(*)
    FROM [Users] AS [u0]) AS [userCount], (
    SELECT COUNT(*)
    FROM [Animals] AS [a]) AS [animalCount]
FROM [Users] AS [u]

(this is quite trivial to check). Batching two selects also has the advantage of possibly reusing query plans when the same SELECT COUNT(*) ... elsewhere (IIRC this isn’t the case with SQL Server semicolon-based batching, but would be the case with DbBatch or on PostgreSQL).

So I do believe #10879 is the right general solution to this. I agree it’s odd for us to do roundtrips only when Where is omitted, but whether that’s worth fixing is an implementation complexity question (so @smitpatel).

1reaction
ajcvickerscommented, Sep 13, 2022

@divega Do you know if you ever created an issue for having a general-purpose context.Query method that could execute any query? I’m sure there must be/have been an issue, since it was something we discussed a lot, but I can’t find one!

Read more comments on GitHub >

github_iconTop Results From Across the Web

EF Core DbContext caching resulted included entities with ...
So it should be a bug. As the query filter in nested properties is not applied on cached elements which will bring unrelated...
Read more >
Should I split a dbcontext with multiple dbsets ...
For a test, I created a separate DbContext and put only one DbSet in it. The DbSet has about 100,000 records, but calling...
Read more >
Advanced Performance Topics
This caching ensures that executing the same LINQ query multiple times is very fast, even if parameter values differ. Consider the following two...
Read more >
Entity Framework Performance and What You Can Do ...
Without a doubt, Entity Framework is a quick and satisfactory way of producing a database-driven web application.
Read more >
Querying data via the DbSet
Queries for retrieving values relating to multiple objects are only executed against a database when the data is iterated over and it is...
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