2014-02-16 29 views
3

我得到試圖運行在下面的代碼塊中的Sitecore的ContentSearch LINQ查詢ToList方法中,當下面的異常信息:Sitecore的ContentSearch LINQ不支持的表達式節點類型:參數

Unsupported expression node type: Parameter. This could be due to ordering of 
expression statements. For example filtering after a select expression like this : 
queryable.Select(i => new { i.Id, i.Title }).Where(i => d.Title > "A" 

public virtual List<SearchResultItem> RunQuery(SearchParam param, bool showAllVersions, bool firstLoad) 
{ 
    Assert.ArgumentNotNull(Index, "Sitecore.SharedSource.Search"); 
    var resultCollection = new List<SearchResultItem>(); 

    try 
    { 
     using (var context = this.Index.CreateSearchContext()) 
     { 
      var result = context.GetQueryable<SearchResultItem>() 
               .Where(x => HasFullText(x, param.FullTextQuery) && 
         HasLanguage(x, param.Language) && 
         HasRelation(x, param.RelatedIds) && 
         HasTemplate(x, param.TemplateIds) && 
         HasLocation(x, param.LocationIds) 
               ); 
      resultCollection = result.ToList(); 
     } 
    } 
    catch (Exception exception) 
    { 
     Log.Error(exception.StackTrace, this); 
     throw; 
    } 

    return resultCollection; 
} 

我不能找出是什麼導致這個問題,我似乎無法用標準的.NET LINQ查詢重現問題,在標準的控制檯應用程序(最終的源代碼)中。

以下是HasLanguage,HasRelation,HasTemplate和HasLocation函數的源代碼。我期望它與這些有關,因爲當我刪除它們並將它們替換爲它們的實現(在可能的情況下),我沒有任何錯誤。但是,查詢內離開的時候,他們甚至不訪問(試過調試):

protected bool HasRefinements(SearchResultItem pseudoResult, SafeDictionary<string> refinements) 
    { 
     if (refinements.Count <= 0) return false; 
     foreach (var refinement in refinements) 
     { 
      var fieldName = refinement.Key.ToLowerInvariant(); 
      var fieldValue = refinement.Value; 
      if (pseudoResult.GetField(fieldName).Value.Equals(IdHelper.ProcessGUIDs(fieldValue))) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

    protected bool HasLanguage(SearchResultItem pseudoResult, string language) 
    { 
     if (String.IsNullOrEmpty(language)) return false; 
     return pseudoResult.GetField(BuiltinFields.Language).Equals(language.ToLowerInvariant()); 
    } 

    protected bool HasFullText(SearchResultItem pseudoResult, string searchText) 
    { 
     if (String.IsNullOrEmpty(searchText)) return false; 
     return pseudoResult.Content.Contains(searchText); 
    } 

    protected bool HasId(SearchResultItem pseudoResult, string fieldName, string filter) 
    { 
     if (String.IsNullOrEmpty(fieldName) || String.IsNullOrEmpty(filter)) return false; 
     var values = IdHelper.ParseId(filter); 
     foreach (var value in values.Where(ID.IsID)) 
     { 
      if (pseudoResult.GetField(fieldName).Value.Equals(IdHelper.ProcessGUIDs(value))) 
      { 
       return true; 
      } 
     } 

     return false; 
    } 

    protected bool HasTemplate(SearchResultItem pseudoResult, string templateIds) 
    { 
     if (String.IsNullOrEmpty(templateIds)) return false; 

     templateIds = IdHelper.NormalizeGuid(templateIds); 
     return pseudoResult.TemplateId.ToString().Equals(templateIds); 
    } 

    protected bool HasLocation(SearchResultItem pseudoResult, string locationIds) 
    { 
     return HasId(pseudoResult, BuiltinFields.Path, locationIds); 
    } 

    protected bool HasRelation(SearchResultItem pseudoResult, string ids) 
    { 
     return HasId(pseudoResult, BuiltinFields.Links, ids); 
    } 

這裏是經常使用LINQ查詢我的測試應用程序的源代碼:

static void Main(string[] args) 
    { 
     Program p = new Program(); 
     p.Process(); 
    } 

    public void Process() 
    { 
     List<Boolean> flags = new List<Boolean>(); 
     flags.Add(true); 
     flags.Add(false); 
     flags.Add(false); 
     flags.Add(true); 
     flags.Add(false); 
     bool b = true; 
     try 
     { 
      List<Boolean> trueFlags = flags 
             .Where<Boolean>(x => IsTrue(x, b)) 
             .ToList(); 
      Console.WriteLine(trueFlags.ToString()); 
      Console.ReadKey(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.StackTrace); 
     } 
    } 

    public bool IsTrue(bool x, bool b) 
    { 
     return x^b; 
    } 

我不能似乎在互聯網上的這個異常消息上找到任何東西。

回答

7

Sitecore LINQ是不是真的像正常的LINQ到.NET中的對象。像LINQ to SQL不像正常的LINQ。

實際情況是,Sitecore解析表達式樹並將您的條件「轉換/翻譯」爲搜索查詢。默認情況下,這是一個Lucene查詢表達式 - 但使用SearchProvider它也可以轉換爲SOLR表達式或Coveo表達式。 以與LINQ to SQL轉換爲SQL表達式相同的方式。 你可以看到LINQ實際上是一個IQueryable,而不是IEnumerable。

在使用IQuerable Sitecore時,必須知道如何將其轉換爲搜索表達式。 Sitecore不知道如何在LINQ表達式中翻譯你的屬性和方法,這就是爲什麼你會得到錯誤。

你應該改變你的表達,只保留可以翻譯的東西或創建一個謂詞。 You should look into the PredicateBuilder

+1

re:謂詞構建器,我還建議在Sitecore 7中構建動態linq查詢這篇文章http://getfishtank.ca/blog/building-dynamic-content-search-linq-queries-in-sitecore- 7 – user495368

相關問題