dotnet / dotnet/efcore

Group By subquery when applied on another Query throws InvalidOperation Exception

Open
#28,258 10 comments 0 reactions 0 assignees View on GitHub
area-groupby area-query customer-reported ef6-parity
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

Not sure, if the same issue is being tracked with some other Id, but when the below combination of query is executed, the EFCore throws InvalidOperationException as listed below:

**Query:**
```
var grpQuery = (from u in context.Users
join usrSites in context.UserSiteAccesses
on (long?)u.Id
equals usrSites.UserId
group new { u, usrSites } by new { u.Id } into usrGrpingRS
select new { usr = usrGrpingRS.FirstOrDefault() }).Distinct();

var anotherQuery = from x in grpQuery
join y in context.UserEmailAddresses on x.usr.usrSites.UserId equals y.UserId
select x;
```
The output of first LINQ (grpQuery):
```
SELECT [t0].[Id], [t0].[CreatedById], [t0].[UserId], [t0].[c]
FROM (
SELECT DISTINCT [u].[Id]
FROM [Users] AS [u]
INNER JOIN [UserSiteAccesses] AS [u0] ON [u].[Id] = [u0].[UserId]
GROUP BY [u].[Id]
) AS [t]
LEFT JOIN (
SELECT [t1].[Id], [t1].[CreatedById], [t1].[UserId], [t1].[c]
FROM (
SELECT [u1].[Id], [u1].[CreatedById], [u2].[UserId], 1 AS [c], ROW_NUMBER() OVER(PARTITION BY [u1].[Id] ORDER BY [u1].[Id], [u2].[Id]) AS [row]
FROM [Users] AS [u1]
INNER JOIN [UserSiteAccesses] AS [u2] ON [u1].[Id] = [u2].[UserId]
) AS [t1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Id] = [t0].[Id]
```
**Exception & Stack Trace: Occurs in the Second LINQ**

```
The LINQ expression 'DbSet()
.Join(
inner: DbSet(),
outerKeySelector: e => (long?)e.Id,
innerKeySelector: e0 => e0.UserId,
resultSelector: (e, e0) => new TransparentIdentifier(
Outer = e,
Inner = e0
))
.GroupBy(ti => new { Id = ti.Outer.Id })
.Select(g => new { usr = g
.AsQueryable()
.Select(e1 => new {
u = IncludeExpression(
IncludeExpression(
e1.Outer,
EF.Property(e1.Outer, "ApprovalStatus"), ApprovalStatus)
,
EF.Property(e1.Outer, "ProfilePicture"), ProfilePicture)
,
usrSites = e1.Inner
})
.FirstOrDefault() })
.Distinct()
.Join(
inner: DbSet(),
outerKeySelector: e3 => e3.usr.usrSites.UserId,
innerKeySelector: e4 => e4.UserId,
resultSelector: (e3, e4) => new TransparentIdentifier<<>f__AnonymousType2<<>f__AnonymousType0>, EUserEmailAddress>(
Outer = e3,
Inner = e4
))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.g__CheckTranslated|15_0(ShapedQueryExpression translated, <>c__DisplayClass15_0& )
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.b__0()
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetEnumerator()
at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()
```

**NOTE:** The same query works fine and produces correct SQL in EF6:

```
First LINQ Query:

SELECT
[Distinct2].[C1] AS [C1],
[Distinct2].[C2] AS [C2],
[Distinct2].[Id] AS [Id],
[Distinct2].[CreatedById] AS [CreatedById],
[Distinct2].[Id1] AS [Id1],
[Distinct2].[CreatedById1] AS [CreatedById1],
[Distinct2].[UserId] AS [UserId],
FROM ( SELECT DISTINCT
1 AS [C1],
[Limit1].[Id] AS [Id],
[Limit1].[CreatedById] AS [CreatedById],
[Limit1].[Id1] AS [Id1],
[Limit1].[CreatedById1] AS [CreatedById1],
[Limit1].[UserId] AS [UserId],
[Limit1].[C1] AS [C2]
FROM (SELECT DISTINCT
[Extent1].[UserId] AS [UserId]
FROM [dbo].[UserSiteAccesses] AS [Extent1] ) AS [Distinct1]
OUTER APPLY (SELECT TOP (1)
[Extent2].[Id] AS [Id],
[Extent2].[CreatedById] AS [CreatedById],
[Extent3].[Id] AS [Id1],
[Extent3].[CreatedById] AS [CreatedById1],
[Extent3].[UserId] AS [UserId],
1 AS [C1]
FROM [dbo].[Users] AS [Extent2]
INNER JOIN [dbo].[UserSiteAccesses] AS [Extent3] ON [Extent2].[Id] = [Extent3].[UserId]
WHERE [Distinct1].[UserId] = [Extent2].[Id] ) AS [Limit1]
) AS [Distinct2]

Second LINQ Query:

SELECT
[Distinct2].[C1] AS [C1],
[Distinct2].[C2] AS [C2],
[Distinct2].[Id] AS [Id],
[Distinct2].[CreatedById] AS [CreatedById],
[Distinct2].[Id1] AS [Id1],
[Distinct2].[CreatedById1] AS [CreatedById1],
[Distinct2].[UserId] AS [UserId],
FROM ( SELECT DISTINCT
1 AS [C1],
[Limit1].[Id] AS [Id],
[Limit1].[CreatedById] AS [CreatedById],
[Limit1].[Id1] AS [Id1],
[Limit1].[CreatedById1] AS [CreatedById1],
[Limit1].[UserId] AS [UserId],
[Limit1].[C1] AS [C2]
FROM (SELECT DISTINCT
[Extent1].[UserId] AS [UserId]
FROM [dbo].[UserSiteAccesses] AS [Extent1] ) AS [Distinct1]
OUTER APPLY (SELECT TOP (1)
[Extent2].[Id] AS [Id],
[Extent2].[CreatedById] AS [CreatedById],
[Extent3].[Id] AS [Id1],
[Extent3].[CreatedById] AS [CreatedById1],
[Extent3].[UserId] AS [UserId],
1 AS [C1]
FROM [dbo].[Users] AS [Extent2]
INNER JOIN [dbo].[UserSiteAccesses] AS [Extent3] ON [Extent2].[Id] = [Extent3].[UserId]
WHERE [Distinct1].[UserId] = [Extent2].[Id] ) AS [Limit1] ) AS [Distinct2]
INNER JOIN [dbo].[UserEmailAddresses] AS [Extent4] ON [Distinct2].[UserId] = [Extent4].[UserId]

```

Models:

```
public partial interface IUser
{
long Id { get; }
long CreatedById { get; }
}

public partial interface IUserSiteAccess
{
long Id { get; }
long? UserId { get; }
long CreatedById { get; }
}
public partial interface IUserEmailAddress
{
long Id { get; }
long? UserId { get; }
string EmailAddress { get; }
long CreatedById { get; }
}
public partial class EUser : IUser
{
public EUser()
{
}

long Id { get; set; }
long CreatedById { get; set; }
}
public partial class EUserSiteAccess : IUserSiteAccess
{
public EUserSiteAccess()
{
}

long Id { get; set; }
long? UserId { get; set;}
long CreatedById { get; set; }
}

public partial class EUserEmailAddress : IUserEmailAddress
{
public EUserEmailAddress()
{
}

long Id { get; set; }
long? UserId { get; set;}
string EmailAddress { get; set; }
long CreatedById { get; set; }
}

public partial class BananaContext : AbstractDbContext
{
public BananaContext()
{
ChangeTracker.AutoDetectChangesEnabled = false;
}

public BananaContext(DbContextOptions options)
{
}
public virtual DbSet UserSiteAccesses { get; set; }
public virtual DbSet Users { get; set; }
public virtual DbSet UserEmailAddresses { get; set; }
}

```

EF Core version: 7.0.0-preview.4.22229.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Win 10 Pro
IDE: Visual Studio 2022 v17.0.4

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.