What is a proper way of using LINQ queries in F# when using a provider (LINQ to NHibernate for example) so as to work the same as in C# (same AST)?
My specific issue is that translating a query to F# throws an error while the C# one works. This might be caused by F# not generating the same AST. Roslyn provides a Visual Studio AST visualizer extension for C# but I am not aware of any AST viewer for F#.
Having the following working C# query:
.First(someEntity => someEntity.SomeNullableInt.HasValue);
when translated to F#:
.First(fun someEntity -> someEntity.SomeNullableInt.HasValue)
it fails with the following error:
System.NotSupportedException: Boolean Invoke(System.Nullable`1[System.Int32])
> at NHibernate.Linq.Visitors.HqlGeneratorExpressionTreeVisitor.VisitMethodCallExpression(MethodCallExpression expression)
at NHibernate.Linq.Visitors.QueryModelVisitor.VisitWhereClause(WhereClause whereClause, QueryModel queryModel, Int32 index)
at Remotion.Linq.QueryModelVisitorBase.VisitBodyClauses(ObservableCollection`1 bodyClauses, QueryModel queryModel)
at Remotion.Linq.QueryModelVisitorBase.VisitQueryModel(QueryModel queryModel)
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, 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, NhLinqExpression& nhQuery)
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
...
Stopped due to error
Using .First(fun someEntity -> someEntity.SomeReferenceType <> null)
works correctly though, which leads to the conclusion above: AST is generated differently in the case of using .HasValue
.