Select entities where ID in int array - WCF Data Services, LINQ

主宰稳场 提交于 2019-11-29 10:55:09

Currently OData (the underlying protocol) doesn't support the Contains operation. So that's why the client library does not translate the above query. People are basically using two ways to overcome this limitation: 1) Use service operations as you noted. 2) Construct a where clause dynamically which uses simple comparisons to compare the value to each item from the array. So if the array contains 1, 2, 3, the where would be data.ID == 1 || data.ID == 2 || data.ID == 3 The #2 solution is nice because it's a client side only change. The downside is, that it only works for small arrays. If the array contains too many items the expression gets too long and that leads to all kinds of troubles. The #1 solution doesn't have the size problem, but you need to provide the operation on the server.

Here is my realization of WhereIn() Method, to filter IQueryable collection by a set of selected entities:

 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;
    }

And calling of this method looks like:

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);

Thank you men you really helped me :) :)

I did it like Vitek Karas said.

1) Download the Dynamic query library Check this link

No need to read it just download the Dynamic query library

2)Check the project named DynamicQuery. In it you will find a class named Dynamic.cs . Copy It to your project

3)Generate your project( If you are using silverlight an error that say ReaderWriterLock is not found will appear. Don't be affraid. Just comment or delete the lines that make errors( there is just 6 or 7 lines that make errors) )

4) All done you just need now to write your query Example: ordersContext.CLIENTS.Where(" NUMCLI > 200 || NUMCLI < 20");

All done. If you have to use the 'Contains' method you just to write a method that iterate over your array and return the string that your request will use.

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

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

        return st;
}

I hope you understand me and that i helped someone :)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!