Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DbSet.Count() in Select() lambda not translating to scalar subquery expression #34958

Open
Bretttt opened this issue Oct 22, 2024 · 5 comments
Open

Comments

@Bretttt
Copy link

Bretttt commented Oct 22, 2024

It appears a DbSet.Count() expression is getting evaluated ahead of time and parameterized.

Example:
var query = dbContext.MyDbSet.Select(v => new
{
v.Id,
Count = dbContext.MyDbSet.Count()
});
string sql = query.ToQueryString();

Expected:

SELECT [v].[Id], (select COUNT(1) from [MyTable]) AS [Count]
FROM [MyTable] AS [v]

Actual:

DECLARE @__Count_0 int = 20;

SELECT [v].[Id], @__Count_0 AS [Count]
FROM [MyTable] AS [v]

Maybe this is by design for some reason I'm not understanding. Thank you

@maumar
Copy link
Contributor

maumar commented Oct 23, 2024

@Bretttt you can prevent parameterization by adding a noop queryable method before count, e.g.

var query = dbContext.MyDbSet.Select(v => new
{
v.Id,
Count = dbContext.MyDbSet.Where(x => true).Count()
});

@maumar
Copy link
Contributor

maumar commented Oct 23, 2024

note: EF8 had the same behavior, so we didn't change/break anything when doing funcletizer rewrite. But this behavior is a bit awkward. e.g.

var query = await ctx.MyEntities.Select(x => new { x.Id, Foo = ctx.MyEntities.Order().FirstOrDefault().Name }).ToListAsync();

will evaluate the subquery (extra round trip):

SELECT TOP(1) [m].[Id], [m].[Name]
FROM [MyEntities] AS [m]
ORDER BY [m].[Id]

exec sp_executesql N'SELECT [m].[Id], @__FirstOrDefault_Name_0 AS [Foo]
FROM [MyEntities] AS [m]',N'@__FirstOrDefault_Name_0 nvarchar(4000)',@__FirstOrDefault_Name_0=N'foo'

while:

 var query = await ctx.MyEntities.Select(x => new { x.Id, Foo = ctx.MyEntities.OrderBy(x => x.Id).FirstOrDefault().Name }).ToListAsync();

will inline:

SELECT [m].[Id], (
    SELECT TOP(1) [m0].[Name]
    FROM [MyEntities] AS [m0]
    ORDER BY [m0].[Id]) AS [Foo]
FROM [MyEntities] AS [m]

@maumar
Copy link
Contributor

maumar commented Oct 23, 2024

/cc @roji

@roji
Copy link
Member

roji commented Oct 23, 2024

The EF8 change with separate evaluation of subqueries was fixed in #33012, which indeed seems related... I agree that the behavior above seems quite wrong, and we shouldn't be evaluating.

@maumar @cincuranet one of you feel like taking a look at this?

@roji roji added the type-bug label Oct 23, 2024
@maumar
Copy link
Contributor

maumar commented Oct 23, 2024

I can take a look, since I peeked into that code already when doing the initial investigation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants