Reputation: 3491
I need to run this query by NHibernate 4 :
var filterList = new List<string> { "1" , "2" } ;
var q = SessionInstance.Query<Book>()
.Where(x => filterList.Any(s => s.StartsWith(x.Code)));
var list = q.ToList();
But it has exception by this message : Specified method is not supported.
StackTrace :
at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.GetClassName(IASTNode querySource)
at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.Process(IASTNode tree)
at NHibernate.Hql.Ast.ANTLR.AstPolymorphicProcessor.Process()
at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(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, NhLinqExpression& nhQuery)
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
at Remotion.Linq.QueryableBase`1.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
Upvotes: 1
Views: 517
Reputation: 123861
This is not implemented, but we can convert such WHERE criteria into OR expression:
var q = SessionInstance
.Query<Book>()
//.Where(x => filterList.Any(s => s.StartsWith(x.Code)))
.Where(x => x.Code.StartsWith("1")
|| x.Code.StartsWith("2")
)
;
Obviously, this is not dynamic. We have to name all OR statements, we cannot use the filterList
... Unless we will ask for help the LinqKit
And create a method to automate that. We would need these using statements:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using LinqKit;
namespace MyNamespace
{
public static partial class Ext
{
...
And the extension itself:
public static Expression<Func<T, bool>> AnyStarts<T>(
this IList<string> startsWithValues, Expression<Func<T, string>> property)
{
var nothingToDo = startsWithValues == null
|| startsWithValues.Count == 0
|| property == null;
// nothing to process here, return null
if (nothingToDo)
{
return null;
}
// first value ...
string firstValue = startsWithValues.First();
Expression<Func<T, bool>> predicate =
x => property.Invoke(x).StartsWith(firstValue);
Expression<Func<T, bool>> result = predicate.Expand();
if (startsWithValues.Count == 1)
{
// first value is enough
return result;
}
// let's append Or if there are many string values
for (int index = 1; index < startsWithValues.Count; index++)
{
string nextValue = startsWithValues[index];
predicate = x => result.Invoke(x)
|| property.Invoke(x).StartsWith(nextValue);
result = predicate.Expand();
}
return result;
}
And we can call it like this:
var filterList = new List<string> { "1" , "2" }; // or more
var q = SessionInstance
.Query<Book>()
//.Where(x => filterList.Any(s => s.StartsWith(x.Code)))
.Where(filterList.AnyStarts<Contact>(x => x.Code))
;
And we will receive any Book, which Code starts with "1", "2", ....
Upvotes: 1