2012-10-08 41 views
0

我有一個搜索框,我已經將數據分成字建。我現在需要將這些單詞與數據庫中的幾個字段進行比較。這裏是我的代碼:LINQ到實體凡遍歷數據

List<string> searchValues = searchString.Split(delimiters, StringSplitOptions.RemoveEmptyEntries).ToList(); 

using (DatabaseEntities context = new DatabaseEntities()) 
{ 
    IQueryable<DatabaseType> returnValue = 
    context.DatabaseType.Where(y => 
     y.Field1.Contains(searchValues[0]) || 
     y.Field1.Contains(searchValues[0])); 

    searchValues.Skip(1).ToList().ForEach(x => 
    { 
     returnValue = returnValue.Where(y => 
      y.Field1.Contains(x) || 
      y.Field2.Contains(x)); 
    }); 

    return returnValue.ToList(); 

我的目標是在實際加載項目到內存之前構建完整的查詢。然而,當我嘗試運行此我得到以下錯誤:

System.NotSupportedException: LINQ to Entities does not recognize the method &#39;System.String get_Item(Int32)&#39; method, and this method cannot be translated into a store expression. 

我原以爲這種類型的錯誤意味着,我在嘗試操作不轉換到SQL工作,但我相當肯定我之前使用過Contains作爲LIKE語句。此外,所有的在數據庫中的信息是nvarchars,所以這些等同於字符串在我的實體。有沒有人知道問題是什麼?使用IQueryable是最好的方法嗎?如果可能的話,我寧願懶加載所有這些。

+2

的聲音有點像它的窒息'searchValues [0]';如果存儲了一個變量,並且使用了'Where'子句中會發生什麼? –

+0

原來,完美的作品。我非常專注於其他我甚至沒有想到的事情。 – PCasagrande

回答

2

的get_Item(的Int32)調用將索引到列表中。在你的情況下,他們是searchValues [0]。用途:

var searchValue = searchValues[0]; 

IQueryable<DatabaseType> returnValue = 
context.DatabaseType.Where(y => 
    y.Field1.Contains(searchValue) || 
    y.Field1.Contains(searchValue)); 
+0

我無法弄清楚在哪裏獲得從當一切都在數據庫中是一個字符串,int值。謝謝。 – PCasagrande

0

我使用該擴展方法下面對生成包含鍵入LINQ到實體表達式(參考原始源是在註釋)。我認爲它也適用於這種情況。

/// <summary> 
    /// Extension method that enables .Contains(obj) like functionality for Linq to Entities. 
    /// 
    /// Source: http://www.velocityreviews.com/forums/t645784-linq-where-clause.html 
    /// </summary> 
    /// <typeparam name="TElement">The element being evaluated by the Where clause</typeparam> 
    /// <typeparam name="TValue">The value to match</typeparam> 
    /// <param name="valueSelector">Lamda for selecting matching values</param> 
    /// <param name="values">IEnumerable of the values</param> 
    /// <returns>Expression consumable by Linq to Entities that reflects semantics of .Contains(value)</returns> 
    /// <remarks> 
    /// Usage: 
    /// 
    /// Replace expression like 
    /// 
    /// where ChildrenIDs.Contains(items.CategoryID) 
    /// 
    /// with 
    /// 
    /// .Where((BuildContainsExpression<Item, int>(item => item.CategoryID, ChildrenIDs)) 
    /// 
    /// NOTE: If the item collection is large, the SQL query will be as well. 
    /// </remarks> 
    static public Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values) 
    { 
     if (null == valueSelector) 
     { 
      throw new ArgumentNullException("valueSelector"); 
     } 
     if (null == values) { throw new ArgumentNullException("values"); } 

     ParameterExpression p = valueSelector.Parameters.Single(); 
     if (!values.Any()) 
     { 
      return e => false; 
     } 

     var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue)))); 
     var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal)); 
     return Expression.Lambda<Func<TElement, bool>>(body, p); 
    } 

實例應用:

var exprWithContains = 
    LinqToEntitiesUtil.BuildContainsExpression<List<int?>, int?> 
     (p => p.ProductYear, productYears); 

var result = (from p in products select p).Where(exprWithContains);