2010-08-19 47 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