Skip to content

ArgumentException thrown When GroupJoin is applied on a DbSet as a first join and NOT when applied as a second or later #27343

Closed
@ankitmatrix08

Description

@ankitmatrix08

1. Exception Case:
LINQ: Here, I have a query which is doing a GroupJoin on an DbSet and then adding other inner joins.
Repository.ConvertToBigIntTable -> This is an output of a call to a Table-Valued function which returns an IQueryable (T is a Keyless entity having a long Id field)

private IQueryable<IDocumentTypePermission> GetDocumentTypePermissionsTest<T>(IQueryable<T> entitySet) where T : class, IDocumentType
        {
            var userGroupIds = RunComponent(GetActiveUserGroupsOfCurrentUser.New(new GetActiveUserGroupsOfCurrentUserParam() { CurrentUserId = CurrentUserId })).UserGroupIds;
            return (from documentType in entitySet
                    join userGroupId in Repository.ConvertToBigIntTable(userGroupIds, "userGroupId")
                    on documentType.Id equals userGroupId.Id into UserGroupIds
                    from userGroupId in UserGroupIds.DefaultIfEmpty()
                    join documentTypePermission in Repository.DocumentTypePermissions
                    on documentType.Id equals documentTypePermission.DocumentTypeId
                    join userSelectionParam in Repository.UserSelectionParams
                    on documentTypePermission.UserSelectionId equals userSelectionParam.Id

                    
                    where documentTypePermission.IsActive && ((userSelectionParam.UserGroupId != null && userGroupId.Id != null)
                                                              || (userSelectionParam.UserId != null && userSelectionParam.UserId == CurrentUserId))
                    select documentTypePermission);
        }
DbSet<EDocumentType>()
    .GroupJoin(
        inner: BananaContext.ConvertCSVToBigIntTable(
            List: <>c__DisplayClass958_0.List, 
            Delim: <>c__DisplayClass958_0.Delim), 
        outerKeySelector: documentType => documentType.Id, 
        innerKeySelector: userGroupId => userGroupId.Id, 
        resultSelector: (documentType, UserGroupIds) => new { 
            documentType = documentType, 
            UserGroupIds = UserGroupIds
         })
    .SelectMany(
        collectionSelector: <>h__TransparentIdentifier0 => <>h__TransparentIdentifier0.UserGroupIds
            .DefaultIfEmpty(), 
        resultSelector: (<>h__TransparentIdentifier0, userGroupId) => new { 
            <>h__TransparentIdentifier0 = <>h__TransparentIdentifier0, 
            userGroupId = userGroupId
         })
    .Join(
        inner: DbSet<EDocumentTypePermission>(), 
        outerKeySelector: <>h__TransparentIdentifier1 => (long?)<>h__TransparentIdentifier1.<>h__TransparentIdentifier0.documentType.Id, 
        innerKeySelector: documentTypePermission => documentTypePermission.DocumentTypeId, 
        resultSelector: (<>h__TransparentIdentifier1, documentTypePermission) => new { 
            <>h__TransparentIdentifier1 = <>h__TransparentIdentifier1, 
            documentTypePermission = documentTypePermission
         })
    .Join(
        inner: DbSet<EUserSelectionParam>(), 
        outerKeySelector: <>h__TransparentIdentifier2 => <>h__TransparentIdentifier2.documentTypePermission.UserSelectionId, 
        innerKeySelector: userSelectionParam => (long?)userSelectionParam.Id, 
        resultSelector: (<>h__TransparentIdentifier2, userSelectionParam) => new { 
            <>h__TransparentIdentifier2 = <>h__TransparentIdentifier2, 
            userSelectionParam = userSelectionParam
         })
    .Where(<>h__TransparentIdentifier3 => <>h__TransparentIdentifier3.<>h__TransparentIdentifier2.documentTypePermission.IsActive && <>h__TransparentIdentifier3.userSelectionParam.UserGroupId != null && (long?)<>h__TransparentIdentifier3.<>h__TransparentIdentifier2.<>h__TransparentIdentifier1.userGroupId.Id != null || <>h__TransparentIdentifier3.userSelectionParam.UserId != null && <>h__TransparentIdentifier3.userSelectionParam.UserId == (long?)AbstractDomainBehavior.CurrentUserId)
    .Select(<>h__TransparentIdentifier3 => <>h__TransparentIdentifier3.<>h__TransparentIdentifier2.documentTypePermission)

Exception:

Expression of type 'System.Func`2[Lw.Domain.IDocumentType,System.Int64]' cannot be used for parameter of type 'System.Linq.Expressions.Expression`1[System.Func`2[Lw.Domain.EDocumentType,System.Int64]]' of method 'System.Linq.IQueryable`1[<>f__AnonymousType290`2[<>f__AnonymousType289`2[Lw.Domain.IDocumentType,System.Collections.Generic.IEnumerable`1[Lw.Sys.Repository.ITableValueFunctionResult]],Lw.Sys.Repository.ITableValueFunctionResult]] LeftJoin[EDocumentType,ITableValueFunctionResult,Int64,<>f__AnonymousType290`2](System.Linq.IQueryable`1[Lw.Domain.EDocumentType], System.Collections.Generic.IEnumerable`1[Lw.Sys.Repository.ITableValueFunctionResult], System.Linq.Expressions.Expression`1[System.Func`2[Lw.Domain.EDocumentType,System.Int64]], System.Linq.Expressions.Expression`1[System.Func`2[Lw.Sys.Repository.ITableValueFunctionResult,System.Int64]], System.Linq.Expressions.Expression`1[System.Func`3[Lw.Domain.EDocumentType,Lw.Sys.Repository.ITableValueFunctionResult,<>f__AnonymousType290`2[<>f__AnonymousType289`2[Lw.Domain.IDocumentType,System.Collections.Generic.IEnumerable`1[Lw.Sys.Repository.ITableValueFunctionResult]],Lw.Sys.Repository.ITableValueFunctionResult]]])' (Parameter 'arg2')

Stack Trace:

   at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
   at System.Linq.Expressions.Expression.Call(MethodInfo method, Expression arg0, Expression arg1, Expression arg2, Expression arg3, Expression arg4)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryableMethodNormalizingExpressionVisitor.TryFlattenGroupJoinSelectMany(MethodCallExpression methodCallExpression)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
   at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryableMethodNormalizingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
   at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryableMethodNormalizingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
   at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryableMethodNormalizingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
   at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryableMethodNormalizingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.NormalizeQueryableMethod(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryTranslationPreprocessor.NormalizeQueryableMethod(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.QueryTranslationPreprocessor.Process(Expression query)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>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.EntityQueryProvider.Execute[TResult](Expression expression)
   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.SystemCore_EnumerableDebugView`1.get_Items()

NOTE: Interestingly trying to do a very similar operation on LinqPad7 seems to work:
image

2. Working Case
LINQ: Here, I have a query which is performing inner joins on few DbSets and then applying GroupJoin on one of the DbSet.
Repository.ConvertToBigIntTable -> This is an output of a call to a Table-Valued function which returns an IQueryable (T is a Keyless entity having a long Id field)

 private IQueryable<IDocumentTypePermission> GetDocumentTypePermissions<T>(IQueryable<T> entitySet) where T : class, IDocumentType
        {
            var userGroupIds = RunComponent(GetActiveUserGroupsOfCurrentUser.New(new GetActiveUserGroupsOfCurrentUserParam() { CurrentUserId = CurrentUserId })).UserGroupIds;
            return (from documentType in entitySet
                    join documentTypePermission in Repository.DocumentTypePermissions on documentType.Id equals documentTypePermission.DocumentTypeId
                    join userSelectionParam in Repository.UserSelectionParams on documentTypePermission.UserSelectionId equals userSelectionParam.Id
                    join userGroupId in Repository.ConvertToBigIntTable(userGroupIds, "userGroupId")
                    on userSelectionParam.UserGroupId equals userGroupId.Id into UserGroupIds
                    from userGroupId in UserGroupIds.DefaultIfEmpty()
                    where documentTypePermission.IsActive && ((userSelectionParam.UserGroupId != null && userGroupId.Id != null)
                                                              || (userSelectionParam.UserId != null && userSelectionParam.UserId == CurrentUserId))
                    select documentTypePermission);
        }

Generated Expression:

DbSet<EDocumentType>()
    .Join(
        inner: DbSet<EDocumentTypePermission>(), 
        outerKeySelector: documentType => (long?)documentType.Id, 
        innerKeySelector: documentTypePermission => documentTypePermission.DocumentTypeId, 
        resultSelector: (documentType, documentTypePermission) => new { 
            documentType = documentType, 
            documentTypePermission = documentTypePermission
         })
    .Join(
        inner: DbSet<EUserSelectionParam>(), 
        outerKeySelector: <>h__TransparentIdentifier0 => <>h__TransparentIdentifier0.documentTypePermission.UserSelectionId, 
        innerKeySelector: userSelectionParam => (long?)userSelectionParam.Id, 
        resultSelector: (<>h__TransparentIdentifier0, userSelectionParam) => new { 
            <>h__TransparentIdentifier0 = <>h__TransparentIdentifier0, 
            userSelectionParam = userSelectionParam
         })
    .GroupJoin(
        inner: BananaContext.ConvertCSVToBigIntTable(
            List: <>c__DisplayClass958_0.List, 
            Delim: <>c__DisplayClass958_0.Delim), 
        outerKeySelector: <>h__TransparentIdentifier1 => <>h__TransparentIdentifier1.userSelectionParam.UserGroupId, 
        innerKeySelector: userGroupId => (long?)userGroupId.Id, 
        resultSelector: (<>h__TransparentIdentifier1, UserGroupIds) => new { 
            <>h__TransparentIdentifier1 = <>h__TransparentIdentifier1, 
            UserGroupIds = UserGroupIds
         })
    .SelectMany(
        collectionSelector: <>h__TransparentIdentifier2 => <>h__TransparentIdentifier2.UserGroupIds
            .DefaultIfEmpty(), 
        resultSelector: (<>h__TransparentIdentifier2, userGroupId) => new { 
            <>h__TransparentIdentifier2 = <>h__TransparentIdentifier2, 
            userGroupId = userGroupId
         })
    .Where(<>h__TransparentIdentifier3 => <>h__TransparentIdentifier3.<>h__TransparentIdentifier2.<>h__TransparentIdentifier1.<>h__TransparentIdentifier0.documentTypePermission.IsActive && <>h__TransparentIdentifier3.<>h__TransparentIdentifier2.<>h__TransparentIdentifier1.userSelectionParam.UserGroupId != null && (long?)<>h__TransparentIdentifier3.userGroupId.Id != null || <>h__TransparentIdentifier3.<>h__TransparentIdentifier2.<>h__TransparentIdentifier1.userSelectionParam.UserId != null && <>h__TransparentIdentifier3.<>h__TransparentIdentifier2.<>h__TransparentIdentifier1.userSelectionParam.UserId == (long?)AbstractDomainBehavior.CurrentUserId)
    .Select(<>h__TransparentIdentifier3 => <>h__TransparentIdentifier3.<>h__TransparentIdentifier2.<>h__TransparentIdentifier1.<>h__TransparentIdentifier0.documentTypePermission)

Generated SQL:

DECLARE @__List_1 nvarchar(4000) = N'1,5,6,7,8,14,15,44,46,62,63,64,67,69,73,85,88';
DECLARE @__Delim_2 nvarchar(1) = N',';
DECLARE @__CurrentUserId_3 bigint = CAST(1 AS bigint);

SELECT [d0].[Id], [d0].[Condition], [d0].[CreatedById], [d0].[CreatedTime], [d0].[DocumentTypeId], [d0].[IsActive], [d0].[IsOverridable], [d0].[IsReevaluate], [d0].[RowVersion], [d0].[UpdatedById], [d0].[UpdatedTime], [d0].[UserSelectionId], [d0].[AssignmentType], [d0].[ConditionFor], [d0].[CreationAllowed], [d0].[Permission]
FROM [DocumentTypes] AS [d]
INNER JOIN [DocumentTypePermissions] AS [d0] ON [d].[Id] = [d0].[DocumentTypeId]
INNER JOIN [UserSelectionParams] AS [u] ON [d0].[UserSelectionId] = [u].[Id]
LEFT JOIN [dbo].[ConvertCSVToBigIntTable](@__List_1, @__Delim_2) AS [c] ON [u].[UserGroupId] = [c].[Id]
WHERE ([d0].[IsActive] = CAST(1 AS bit)) AND (([u].[UserGroupId] IS NOT NULL AND [c].[Id] IS NOT NULL) OR ([u].[UserId] IS NOT NULL AND ([u].[UserId] = @__CurrentUserId_3)))

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

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions