2010-08-19 58 views
6

我想返回一組實體,這些實體擁有和包含在使用LINQ和數據服務的ID列表或ID數組中的ID。我知道如何使用LinqToEF,但我對如何使用Data Services或使用OData查詢約定感到茫然。選擇int數組中的ID - WCF數據服務,LINQ

我的想法是,我會做這樣的事情:

int[] intArray = {321456, 321355, 218994, 189232}; 
var query = (from data in context.Entity 
      where intArray.contains(data.ID) 
      select data); 

有沒有辦法使用數據服務/ OData的完成?我知道我可能會通過服務操作來破解它,但我不希望這樣做。

乾杯。

回答

8

當前OData(底層協議)不支持Contains操作。所以這就是客戶端庫不翻譯上述查詢的原因。 人們基本上使用兩種方法來克服這個限制: 1)使用服務操作,如你所述。 2)動態構造一個where子句,它使用簡單的比較來比較該值與數組中的每個項目。所以如果數組包含1,2,3,那麼將會是data.ID == 1 || data.ID == 2 || data.ID == 3 #2解決方案非常好,因爲它只是客戶端的改變。缺點是,它只適用於小型陣列。如果數組中包含太多項目,表達式會變得太長,並導致各種麻煩。 #1解決方案沒有尺寸問題,但需要在服務器上提供該操作。

+0

「動態構建where子句,它使用簡單比較將該值與數組中的每個項目進行比較「 - 您能否提供一個示例。 – 2011-03-10 02:18:09

+0

例子會很長 - 你可能會搜索「動態LINQ」等。低級方法是使用Expression類及其API以編程方式構建LINQ查詢。 – 2011-03-10 08:57:16

0

謝謝你的男人真的幫了我:) :)

我做到了像維特克卡拉斯說。

1)下載的動態查詢庫 入住這link

沒有必要讀它剛纔下載的動態查詢庫

2)檢查項目命名DynamicQuery。在其中您將找到一個名爲Dynamic.cs的類。將它複製到你的項目中

3)生成你的項目(如果你使用的是Silverlight,會出現一個錯誤信息,說明沒有找到ReaderWriterLock,不要擔心,只需註釋或刪除出錯的行6個或7行,使錯誤))

4)全部完成你剛纔需要編寫查詢 例子:ordersContext.CLIENTS.Where(" NUMCLI > 200 || NUMCLI < 20");

全部完成。如果您必須使用'Contains'方法,您只需編寫一個迭代數組並返回請求將使用的字符串的方法。

private string MyFilter() 
{ string st = ""; 

     foreach(var element in myTab) 
     { 
       st = st + "ThePropertyInTheTable =" + element + "||"; 
     } 

     return st; 
} 

我希望你明白我,我幫助別人:)

+0

當請求太長時,此解決方案會導致問題。所以我找到了另一個使用AddQueryOption並使用$ filter這樣的解決方案:DataServiceQuery ordersQuery =(DataServiceQuery )this.context.CLIENTS.AddQueryOption(「$ filter」,MyFilter()); – ihebiheb 2012-09-20 11:40:39

+0

不要使用大寫AND。它導致和錯誤。使用而不是與。 – ihebiheb 2012-09-20 11:45:04

3

這是我實現的,其中()方法,由一組選定的實體篩選IQueryable的集合:

public static IQueryable<T> WhereIn<T,TProp>(this IQueryable<T> source, Expression<Func<T,TProp>> memberExpr, IEnumerable<TProp> values) where T : class 
    { 
     Expression predicate = null; 
     ParameterExpression param = Expression.Parameter(typeof(T), "t"); 

     bool IsFirst = true; 

     // Create a comparison for each value eg:     
     // IN: t => t.Id == 1 | t.Id == 2     

     MemberExpression me = (MemberExpression) memberExpr.Body; 
     foreach (TProp val in values) 
     { 
      ConstantExpression ce = Expression.Constant(val); 


      Expression comparison = Expression.Equal(me, ce); 

      if (IsFirst) 
      { 
       predicate = comparison; 
       IsFirst = false; 
      } 
      else 
      { 
       predicate = Expression.Or(predicate, comparison); 
      } 
     } 

     return predicate != null 
      ? source.Where(Expression.Lambda<Func<T, bool>>(predicate, param)).AsQueryable<T>() 
      : source; 
    } 

並且調用此方法如下所示:

IQueryable<Product> q = context.Products.ToList(); 

var SelectedProducts = new List<Product> 
{ 
    new Product{Id=23}, 
    new Product{Id=56} 
}; 
... 
// Collecting set of product id's  
var selectedProductsIds = SelectedProducts.Select(p => p.Id).ToList(); 

// Filtering products 
q = q.WhereIn(c => c.Product.Id, selectedProductsIds); 
+2

非常好。但是,它會產生一個意外的結果,即將空數組作爲輸入。你會期望沒有結果的空數組中沒有任何東西,但它會返回一切。考慮到這一點,我已將return語句更改爲: return predicate!= null ? source.Where(Expression.Lambda >(predicate,param))。AsQueryable () :source.Where(x => false).AsQueryable (); – 2015-02-06 13:38:42