nhibernate / nhibernate-core

NHibernate Object Relational Mapper
https://nhibernate.info
GNU Lesser General Public License v2.1
2.13k stars 929 forks source link

Linq contains on a value collection is failing #2465

Closed dvdwouwe closed 4 years ago

dvdwouwe commented 4 years ago

When upgrading from 5.2.7 -> 5.3.1, I noticed we had a problem with a kind of large linq-statement, this is a linq statement build dynamically. I tried already 5.3.2-dev, but no luck.

This is the sql query from 5.2.7 that was generated:

select cast(count(*) as INT) as col_0_0_
from   [dbo].[FollowUp] followupto0_
       left outer join [dbo].[FollowUpTodoParticipant] followupto1_
         on followupto0_.[ExecutorId] = followupto1_.[FollowUpTodoParticipantId]
       left outer join [dbo].[Sector] sector2_
         on followupto1_.[SectorId] = sector2_.[SectorId]
       left outer join [dbo].[RegionStructure] regionstru3_
         on followupto1_.[RegionId] = regionstru3_.[RegionStructureId]
where  followupto0_.[Discriminator] = 'FOLLOW_UP_TODO'
       and (followupto0_.[ShowFromDate] is null
             or followupto0_.[ShowFromDate] <= '2020-08-02T10:01:34.7699488' /* @p0 */)
       and followupto0_.[Active] = 1 /* @p1 */
       and (followupto0_.[Concerns] = 'MEMBER' /* @p2 */
            and (exists (select identityau4_.[IdentityAuthorizationId]
                         from   [dbo].[IdentityAuthorization] identityau4_
                                inner join [dbo].[Identity] identity5_
                                  on identityau4_.[IdentityId] = identity5_.[IdentityId]
                         where  identity5_.[IdentityName] = 'ppw' /* @p3 */
                                and identityau4_.[Permission] = 23 /* @p4 */
                                and identityau4_.[Action] & 1 /* @p5 */ > 0 /* @p6 */
                                and identityau4_.[SectorVector] & sector2_.[BitMask] = sector2_.[BitMask]
                                and identityau4_.[RegionStructureVector] & regionstru3_.[BitMask] = regionstru3_.[BitMask]))
             or followupto0_.[Concerns] = 'COMPANY' /* @p7 */
                and (exists (select identityau6_.[IdentityAuthorizationId]
                             from   [dbo].[IdentityAuthorization] identityau6_
                                    inner join [dbo].[Identity] identity7_
                                      on identityau6_.[IdentityId] = identity7_.[IdentityId]
                             where  identity7_.[IdentityName] = 'ppw' /* @p8 */
                                    and identityau6_.[Permission] = 41 /* @p9 */
                                    and identityau6_.[Action] & 1 /* @p10 */ > 0 /* @p11 */
                                    and identityau6_.[SectorVector] & sector2_.[BitMask] = sector2_.[BitMask]
                                    and identityau6_.[RegionStructureVector] & regionstru3_.[BitMask] = regionstru3_.[BitMask]))
             or followupto0_.[Concerns] = 'TBE' /* @p12 */
                and (exists (select identityau8_.[IdentityAuthorizationId]
                             from   [dbo].[IdentityAuthorization] identityau8_
                                    inner join [dbo].[Identity] identity9_
                                      on identityau8_.[IdentityId] = identity9_.[IdentityId]
                             where  identity9_.[IdentityName] = 'ppw' /* @p13 */
                                    and identityau8_.[Permission] = 111 /* @p14 */
                                    and identityau8_.[Action] & 1 /* @p15 */ > 0 /* @p16 */
                                    and identityau8_.[SectorVector] & sector2_.[BitMask] = sector2_.[BitMask]
                                    and identityau8_.[RegionStructureVector] & regionstru3_.[BitMask] = regionstru3_.[BitMask]))
             or followupto0_.[Concerns] = 'JURIDICAL_FILE' /* @p17 */
                and (exists (select identityau10_.[IdentityAuthorizationId]
                             from   [dbo].[IdentityAuthorization] identityau10_
                                    inner join [dbo].[Identity] identity11_
                                      on identityau10_.[IdentityId] = identity11_.[IdentityId]
                             where  identity11_.[IdentityName] = 'ppw' /* @p18 */
                                    and identityau10_.[Permission] = 75 /* @p19 */
                                    and identityau10_.[Action] & 1 /* @p20 */ > 0 /* @p21 */
                                    and identityau10_.[SectorVector] & sector2_.[BitMask] = sector2_.[BitMask]
                                    and identityau10_.[RegionStructureVector] & regionstru3_.[BitMask] = regionstru3_.[BitMask]))
             or followupto0_.[Concerns] = 'EXTERNAL_PERSON' /* @p22 */
                and (followupto1_.[RegionId] is not null)
                and (exists (select identityau12_.[IdentityAuthorizationId]
                             from   [dbo].[IdentityAuthorization] identityau12_
                                    inner join [dbo].[Identity] identity13_
                                      on identityau12_.[IdentityId] = identity13_.[IdentityId]
                             where  identity13_.[IdentityName] = 'ppw' /* @p23 */
                                    and identityau12_.[Permission] = 7 /* @p24 */
                                    and identityau12_.[Action] & 1 /* @p25 */ > 0 /* @p26 */))
             or followupto0_.[Concerns] = 'EXTERNAL_COMPANY' /* @p27 */
                and (followupto1_.[RegionId] is not null)
                and (exists (select identityau14_.[IdentityAuthorizationId]
                             from   [dbo].[IdentityAuthorization] identityau14_
                                    inner join [dbo].[Identity] identity15_
                                      on identityau14_.[IdentityId] = identity15_.[IdentityId]
                             where  identity15_.[IdentityName] = 'ppw' /* @p28 */
                                    and identityau14_.[Permission] = 31 /* @p29 */
                                    and identityau14_.[Action] & 1 /* @p30 */ > 0 /* @p31 */))
             or followupto0_.[Concerns] = 'WORKER_REPRESENTATION' /* @p32 */
                and (exists (select identityau16_.[IdentityAuthorizationId]
                             from   [dbo].[IdentityAuthorization] identityau16_
                                    inner join [dbo].[Identity] identity17_
                                      on identityau16_.[IdentityId] = identity17_.[IdentityId]
                             where  identity17_.[IdentityName] = 'ppw' /* @p33 */
                                    and identityau16_.[Permission] = 103 /* @p34 */
                                    and identityau16_.[Action] & 1 /* @p35 */ > 0 /* @p36 */
                                    and identityau16_.[SectorVector] & sector2_.[BitMask] = sector2_.[BitMask]
                                    and identityau16_.[RegionStructureVector] & regionstru3_.[BitMask] = regionstru3_.[BitMask]))
             or followupto0_.[Concerns] = 'COURSE' /* @p37 */
                and (exists (select identityau18_.[IdentityAuthorizationId]
                             from   [dbo].[IdentityAuthorization] identityau18_
                                    inner join [dbo].[Identity] identity19_
                                      on identityau18_.[IdentityId] = identity19_.[IdentityId]
                             where  identity19_.[IdentityName] = 'ppw' /* @p38 */
                                    and identityau18_.[Permission] = 141 /* @p39 */
                                    and identityau18_.[Action] & 1 /* @p40 */ > 0 /* @p41 */
                                    and identityau18_.[SectorVector] & sector2_.[BitMask] = sector2_.[BitMask]
                                    and identityau18_.[RegionStructureVector] & regionstru3_.[BitMask] = regionstru3_.[BitMask]))
             or followupto0_.[Concerns] = 'COURSE_PERSON' /* @p42 */
                and (exists (select identityau20_.[IdentityAuthorizationId]
                             from   [dbo].[IdentityAuthorization] identityau20_
                                    inner join [dbo].[Identity] identity21_
                                      on identityau20_.[IdentityId] = identity21_.[IdentityId]
                             where  identity21_.[IdentityName] = 'ppw' /* @p43 */
                                    and identityau20_.[Permission] = 141 /* @p44 */
                                    and identityau20_.[Action] & 1 /* @p45 */ > 0 /* @p46 */
                                    and identityau20_.[SectorVector] & sector2_.[BitMask] = sector2_.[BitMask]
                                    and identityau20_.[RegionStructureVector] & regionstru3_.[BitMask] = regionstru3_.[BitMask]))
             or exists (select followupro23_.[FollowUpRoleId]
                        from   [dbo].[FollowUpRoleToFollowUpTodoParticipant] roles22_,
                               [dbo].[FollowUpRole] followupro23_
                        where  followupto1_.[FollowUpTodoParticipantId] = roles22_.[FollowUpTodoParticipantId]
                               and roles22_.[FollowUpRoleId] = followupro23_.[FollowUpRoleId]
                               and (exists (select followupro24_.[FollowUpRoleUserId]
                                            from   [dbo].[FollowUpRoleUser] followupro24_
                                            where  followupro23_.[FollowUpRoleId] = followupro24_.[RoleId]
                                                   and followupro24_.[IdentityName] = 'ppw' /* @p47 */)))
             or exists (select identityna25_.IdentityName
                        from   [dbo].FollowUpTodoParticipantUser identityna25_
                        where  followupto1_.[FollowUpTodoParticipantId] = identityna25_.TodoParticipantId
                               and identityna25_.IdentityName = 'ppw' /* @p48 */))

I got this stack-frame on the 5.3.1 package:

> Request GetTodoCounter for class FollowUpTodo failed
> PPWCode.Vernacular.Exceptions.III.ExternalError: Request GetTodoCounter for class FollowUpTodo failed ---> NHibernate.TypeMismatchException: left and right hand sides of a binary logic operator were incompatibile [String : System.Collections.Generic.ICollection`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]](ABVV.New.Phoenix.Server.Model.FollowUp.FollowUpTodoParticipant.IdentityNames)]
>    at NHibernate.Hql.Ast.ANTLR.Tree.BinaryLogicOperatorNode.MutateRowValueConstructorSyntaxesIfNecessary(IType lhsType, IType rhsType)
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.comparisonExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.whereClause()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.unionedQuery()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.query()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.collectionFunctionOrSubselect()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.comparisonExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.whereClause()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.unionedQuery()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.query()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.collectionFunctionOrSubselect()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.comparisonExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.logicalExpr()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.whereClause()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.unionedQuery()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.query()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.selectStatement()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlWalker.statement()
>    at NHibernate.Hql.Ast.ANTLR.HqlSqlTranslator.Translate()
>    at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.Analyze(String collectionRole)
>    at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.DoCompile(IDictionary`2 replacements, Boolean shallow, String collectionRole)
>    at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IQueryExpression queryExpression, IASTNode ast, String queryIdentifier, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
>    at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary`2 filters, ISessionFactoryImplementor factory)
>    at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters)
>    at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow)
>    at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
>    at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query)
>    at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
>    at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
>    at ABVV.New.Phoenix.Server.Repository.FollowUp.FollowUpTodoRepository.<>c__DisplayClass8_0.<GetTodoCounter>b__0() in V:\cmb-newphoenix-api\src\ABVV.New.Phoenix.Server\Repository\FollowUp\FollowUpTodoRepository.cs:line 57
>    at PPWCode.Vernacular.NHibernate.II.Providers.SafeEnvironmentProvider.Run[TResult](Func`1 startMessage, Func`1 finishedMessage, Func`1 failedMessage, Func`1 func)
>    --- End of inner exception stack trace ---
>    at PPWCode.Vernacular.NHibernate.II.Providers.SafeEnvironmentProvider.Run[TResult](Func`1 startMessage, Func`1 finishedMessage, Func`1 failedMessage, Func`1 func)
>    at PPWCode.Vernacular.NHibernate.II.Providers.SafeEnvironmentProvider.Run[TEntity,TId,TResult](String requestDescription, Func`1 func, TEntity entity)
>    at PPWCode.Vernacular.NHibernate.II.RepositoryBase`2.<>c__DisplayClass15_0`1.<Execute>b__0()
>    at PPWCode.Vernacular.NHibernate.II.Providers.TransactionProvider.Run[TResult](ISession session, IsolationLevel isolationLevel, Func`1 func)
>    at PPWCode.Vernacular.NHibernate.II.RepositoryBase`2.Execute[TResult](String requestDescription, Func`1 func, TRoot entity)
>    at PPWCode.Vernacular.NHibernate.II.RepositoryBase`2.Execute[TResult](String requestDescription, Func`1 func)
>    at ABVV.New.Phoenix.Server.Repository.FollowUp.FollowUpTodoRepository.GetTodoCounter(FollowUpTodoSearchCriteria criteria) in V:\cmb-newphoenix-api\src\ABVV.New.Phoenix.Server\Repository\FollowUp\FollowUpTodoRepository.cs:line 55
>    at ABVV.New.Phoenix.Server.BusinessLogic.FollowUp.FollowUpTodoManager.GetTodoCounter(FollowUpTodoSearchCriteria criteria) in V:\cmb-newphoenix-api\src\ABVV.New.Phoenix.Server\BusinessLogic\FollowUp\FollowUpTodoManager.cs:line 59
>    at ABVV.New.Phoenix.Server.API.I.FollowUps.FollowUpTodoSearchController.Counter() in V:\cmb-newphoenix-api\src\ABVV.New.Phoenix.Server\API\I\FollowUps\FollowUpTodoSearchController.cs:line 81
>    at lambda_method(Closure , Object , Object[] )
>    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters)
>    at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()
> --- End of stack trace from previous location where exception was thrown ---
>    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
>    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
>    at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()
> 

After some digging in the stacktrace and the nhibernate code I found out that it had todo with the last generated sql fragment:

         or exists (select identityna25_.IdentityName
                        from   [dbo].FollowUpTodoParticipantUser identityna25_
                        where  followupto1_.[FollowUpTodoParticipantId] = identityna25_.TodoParticipantId
                               and identityna25_.IdentityName = 'ppw' /* @p48 */))

Here are our class definition for the two evolved classes:

<class name="FollowUpTodoParticipant" table="`FollowUpTodoParticipant`" schema="`dbo`" abstract="false" dynamic-update="true" batch-size="320">
    <id name="Id" access="nosetter.camelcase-underscore" column="`FollowUpTodoParticipantId`" type="Int64">
      <generator class="hilo">
        <param name="table">HIBERNATE_HI_LO</param>
        <param name="column">NEXT_HI</param>
        <param name="max_lo">999</param>
        <param name="where">ENTITY_NAME = 'FollowUpTodoParticipant'</param>
      </generator>
    </id>
    <many-to-one name="Sector" column="`SectorId`" index="IX_FK_FollowUpTodoParticipant_SectorId" foreign-key="FK_FollowUpTodoParticipant_SectorId" />
    <many-to-one name="Region" column="`RegionId`" index="IX_FK_FollowUpTodoParticipant_RegionId" foreign-key="FK_FollowUpTodoParticipant_RegionId" />
    <set name="Roles" access="nosetter.camelcase-underscore" table="`FollowUpRoleToFollowUpTodoParticipant`" schema="`dbo`" cascade="save-update, persist" batch-size="320">
      <key column="`FollowUpTodoParticipantId`" />
      <many-to-many class="FollowUpRole" foreign-key="FK_FollowUpRoleToFollowUpTodoParticipant_FollowUpRoleId">
        <column name="`FollowUpRoleId`" index="IX_FK_FollowUpRoleToFollowUpTodoParticipant_FollowUpRoleId" />
      </many-to-many>
    </set>
    <bag name="IdentityNames" access="nosetter.camelcase-underscore" table="FollowUpTodoParticipantUser" schema="`dbo`" batch-size="320">
      <key column="TodoParticipantId" />
      <element type="String">
        <column name="IdentityName" index="IX_FollowUpTodoParticipantUser_IdentityName" />
      </element>
    </bag>
  </class>

<subclass name="FollowUp.FollowUpTodo" discriminator-value="FOLLOW_UP_TODO" dynamic-update="true" extends="FollowUpNonTemplate" abstract="false" batch-size="320">
    <property name="Comment" column="`Comment`" />
    <property name="ShowFromDate" type="NHibernate.Type.UtcDateTimeType, NHibernate, Version=5.3.0.0, Culture=neutral, PublicKeyToken=aa95f207798dfdb4" column="`ShowFromDate`" />
    <property name="ExpirationDate" type="NHibernate.Type.UtcDateTimeType, NHibernate, Version=5.3.0.0, Culture=neutral, PublicKeyToken=aa95f207798dfdb4" column="`ExpirationDate`" />
    <property name="CompletedAt" type="NHibernate.Type.UtcDateTimeType, NHibernate, Version=5.3.0.0, Culture=neutral, PublicKeyToken=aa95f207798dfdb4" column="`CompletedAt`" />
    <property name="CompletedBy" column="`CompletedBy`" />
    <property name="ReopenedAt" type="NHibernate.Type.UtcDateTimeType, NHibernate, Version=5.3.0.0, Culture=neutral, PublicKeyToken=aa95f207798dfdb4" column="`ReopenedAt`" />
    <property name="ReopenedBy" column="`ReopenedBy`" />
    <many-to-one name="Applicant" column="`ApplicantId`" index="IX_FK_FollowUpTodo_ApplicantId" cascade="all,delete-orphan" foreign-key="FK_FollowUpTodo_ApplicantId" />
    <many-to-one name="Executor" column="`ExecutorId`" index="IX_FK_FollowUpTodo_ExecutorId" cascade="all,delete-orphan" foreign-key="FK_FollowUpTodo_ExecutorId" />
  </subclass>

It seems to fail in MutateRowValueConstructorSyntaxesIfNecessary when they calculate the column-span of the left and right operands. For a collection type you get 0.

So, I tried to create a faling unit-test, but i was surprised that I got a failing unit-test, but not with the same stacktrace we got in our project.

namespace NHibernate.Test.NHSpecificTest.GHxxxx
{
    class Applicant
    {
        private readonly IList<string> _identityNames = new List<string>();
        public virtual Guid Id { get; set; }
        public virtual IList<string> IdentityNames => _identityNames;
    }
}

namespace NHibernate.Test.NHSpecificTest.GHxxxx
{
    [TestFixture]
    public class Fixture : BugTestCase
    {
        protected override void OnSetUp()
        {
            using (var session = OpenSession())
            using (var transaction = session.BeginTransaction())
            {
                var applicant = new Applicant {IdentityNames = {"name1", "name2"}};
                session.Save(applicant);

                transaction.Commit();
            }
        }

        protected override void OnTearDown()
        {
            using (var session = OpenSession())
            using (var transaction = session.BeginTransaction())
            {
                session.Delete("from System.Object");
                transaction.Commit();
            }
        }

        [Test]
        public void ContainsInsideValueCollection()
        {
            using (var session = OpenSession())
            using (var transaction = session.BeginTransaction())
            {
                var identityNames = new[] {"name1", "x"};
                var query =
                    session
                        .Query<Applicant>()
                        .Where(a => a.IdentityNames.Any(n => identityNames.Contains(n)));
                var result = query.ToList();
                transaction.Commit();
            }
        }
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernate.Test"
                   namespace="NHibernate.Test.NHSpecificTest.GHxxxx">

  <class name="Applicant">
    <id name="Id" generator="guid.comb"/>
    <bag name="IdentityNames" access="nosetter.camelcase-underscore" table="ApplicantUser">
      <key column="ApplicantId"/>
      <element type="String">
        <column name="IdentityName"/>
      </element>
    </bag>
  </class>
</hibernate-mapping>

This test is also failing and was quite simple to reproduce. It seems also that GetColumnSpan is returning zero when trying to solve the number of parameters, using GetIdsForBackTrack.

But I'm still trying to reproduce our case, because I believe we have two different cases.

maca88 commented 4 years ago

Thanks for the detailed description and the provided unit test. I made a fix for both cases in #2467.

But I'm still trying to reproduce our case, because I believe we have two different cases.

I was able to reproduce the first issue by using an equal operator instead of Contains method:

.Where(a => a.IdentityNames.Any(n => n == "name1"));
dvdwouwe commented 4 years ago

Will this fix be included in the 5.3.2 release?

dvdwouwe commented 4 years ago

I appreciate your effort and quick response, thx to @maca88 and @fredericDelaporte, and the nHibernate team-members!

fredericDelaporte commented 4 years ago

Fixed by #2467