2
votes

I'm trying to optimize two requests to DB into one like this:

    var subQuery = Session
        .Query<IProfile>()
        .Where(profile => accountIds.Contains(profile.AccountId))
        .GroupBy(profile => profile.AccountId)
        .Select(kv => kv.Max(profile => profile.Id));
        //.ToList();

    var outQuery = Session
        .Query<IProfile>()
        .Where(profile => subQuery.Contains(profile.Id))
        .Fetch(profile => profile.User)
        .Fetch(profile => profile.Email);

    var result = outQuery.ToList();

but this produse an System.ArgumentException

but if it is two separate requests to DB like this

    var subQuery = Session
        .Query<IProfile>()
        .Where(profile => accountIds.Contains(profile.AccountId))
        .GroupBy(profile => profile.AccountId)
        .Select(kv => kv.Max(profile => profile.Id))
        .ToList();

everything work properly.

More info about exception:

'System.Nullable1[System.Int64]' cannot be used as the data type for a sequence with an ItemExpression of type 'System.Nullable1[System.Int64]'. Parameter name: dataType

at Remotion.Linq.Clauses.StreamedData.StreamedSequenceInfo.AdjustDataType(Type dataType) at Remotion.Linq.QueryModel.GetOutputDataInfo() at Remotion.Linq.QueryModel.GetResultType() at NHibernate.Linq.NestedSelects.NestedSelectRewriter.ProcessSubquery(ISessionFactory sessionFactory, ICollection1 elementExpression, QueryModel queryModel, Expression group, QueryModel subQueryModel) at NHibernate.Linq.NestedSelects.NestedSelectRewriter.ProcessExpression(QueryModel queryModel, ISessionFactory sessionFactory, Expression expression, List1 elementExpression, ParameterExpression group) at NHibernate.Linq.NestedSelects.NestedSelectRewriter.ReWrite(QueryModel queryModel, ISessionFactory sessionFactory) at NHibernate.Linq.Visitors.QueryModelVisitor.GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, Boolean root) at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitSubQueryExpression(SubQueryExpression expression) at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitExpression(Expression expression) at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.Visit(Expression expression, VisitorParameters parameters) at NHibernate.Linq.Visitors.QueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index) at Remotion.Linq.Clauses.WhereClause.Accept(IQueryModelVisitor visitor, QueryModel queryModel, Int32 index) at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection1 bodyClauses, QueryModel queryModel) at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel) at NHibernate.Linq.Visitors.QueryModelVisitor.Visit()
at NHibernate.Linq.Visitors.QueryModelVisitor.GenerateHqlQuery(QueryModel queryModel, VisitorParameters parameters, Boolean root) at NHibernate.Linq.NhLinqExpression.Translate(ISessionFactoryImplementor sessionFactory, Boolean filter) at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary2 filters, ISessionFactoryImplementor factory) at NHibernate.Engine.Query.QueryExpressionPlan.CreateTranslators(IQueryExpression queryExpression, String collectionRole, Boolean shallow, IDictionary2 enabledFilters, ISessionFactoryImplementor factory) at NHibernate.Engine.Query.QueryExpressionPlan..ctor(IQueryExpression queryExpression, Boolean shallow, IDictionary2 enabledFilters, ISessionFactoryImplementor factory) at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow, IDictionary2 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, NhLinqExpression& nhQuery) at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression) at Remotion.Linq.QueryableBase1.GetEnumerator() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)

1

1 Answers

0
votes

Can you try to rewrite the two queries combined like this:

Session.Query<IProfile>()
    .Where(profile => 
        Session.Query<IProfile>()
           .Where(pf => accountIds.Contains(pf.AccountId))
           .GroupBy(pf => pf.AccountId)
           .Select(kv => kv.Max(pf => pf.Id)) // subQuery
           .Any(id => profile.Id == id)) // outQuery
    .Fetch(profile => profile.User)
    .Fetch(profile => profile.Email);