2015-05-05 33 views
1

我需要NHibernate的4运行此查询:如何LINQ到NHibernate的2个列表之间通过StartsWith

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(); 

但此消息有例外:Specified method is not supported.

堆栈跟踪:

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) 

回答

1

这没有实现,但我们可以将WHERE 标准转换为OR表达:

var q = SessionInstance 
    .Query<Book>() 
    //.Where(x => filterList.Any(s => s.StartsWith(x.Code))) 
    .Where(x => x.Code.StartsWith("1") 
      || x.Code.StartsWith("2") 
    ) 
    ; 

显然,这是不动态。我们必须命名所有或声明,我们不能使用filterList ...除非我们要求帮助LinqKit

,并创建一个方法自动化。我们需要这些using语句:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using LinqKit; 

namespace MyNamespace 
{ 
    public static partial class Ext 
    { 
     ... 

和扩展本身:

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; 
} 

我们可以这样调用:

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)) 
    ; 

我们将接受任何图书,其中代码以“1”,“2”,...开头。

相关问题