选择int数组中ID的实体 - WCF数据服务,LINQ

gom*_*ala 6 c# linq wcf-data-services

我想使用LINQ和Data Services返回一组实体,这些实体具有包含在ID列表或数组中的ID和ID.我知道如何使用LinqToEF,但我不知道如何使用Data Services或使用OData查询约定.

我的想法是我会做类似的事情:

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

有没有办法使用Data Services/OData?我知道我可能会通过服务操作破解它,但我宁愿不这样做.

干杯.

Vit*_*SFT 8

目前OData(底层协议)不支持Contains操作.这就是客户端库不翻译上述查询的原因.人们基本上使用两种方法来克服这种限制:1)如你所指出的那样使用服务操作.2)动态构造一个where子句,它使用简单的比较来比较数组中每个项的值.因此,如果数组包含1,2,3,那么data.ID == 1 || data.ID == 2 || data.ID == 3#2解决方案很好,因为它只是客户端改变.缺点是,它只适用于小型阵列.如果数组包含太多项,则表达式会变得太长,从而导致各种麻烦.#1解决方案没有大小问题,但您需要在服务器上提供操作.


Fra*_*ent 5

这是我对WhereIn()方法的实现,通过一组选定的实体来过滤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;
    }
Run Code Online (Sandbox Code Playgroud)

该方法的调用如下所示:

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);
Run Code Online (Sandbox Code Playgroud)

  • 很不错。然而,它确实以空数组作为输入给出了意外的结果。您可能希望该空数组中没有任何内容,从而导致没有结果,但它却返回所有内容。考虑到这一点,我将 return 语句更改为: return predicate != null ? source.Where(Expression.Lambda&lt;Func&lt;T, bool&gt;&gt;(predicate, param)).AsQueryable&lt;T&gt;() : source.Where(x =&gt; false).AsQueryable&lt;T&gt;(); (4认同)