Passing multiple values in a Where clause when calling RIA services from Silverlight
We recently worked on a project where we wanted to pass multiple values in a Where clause when calling RIA services. The issue seems trivial when we think of where...in clause in TSQL, but for RIA services, we need a little extra tricks. Rather than letting the good research go waste, I am publishing the details here.
Say, you have a Product-related database table which is mapped into "Product" entity inside RIA domain services. The context is named as "productContext". Product entity contains ProductID and few other columns. We want to query the Product entity for ProductID=10,20,30. So, lets write the query:
EntityQuery<Product> listProduct = from p in productContext.GetProductsQuery()
where p.ProductID in (10,20,30)
select p;
Guess what, it does not work in RIA context. The "in" is not a valid syntax when calling RIA services.
Good news is, you can build a predicate expression that does exactly what "in" would do.
Expression:
static Expression<Func<Product, bool>> BuiltInExpression(int[] ids)
{
var inputExpression = Expression.Parameter(typeof(Product), "input");
var valueExpression = Expression.Property(inputExpression, s_propertyInfo);
var inExpression =
ids
.Aggregate(
default(Expression),
(acc, v) =>
{
var vExpression = Expression.Constant(v, typeof(int?));
var compareExpression = Expression.Equal(valueExpression, vExpression);
if (acc == null)
{
return compareExpression;
}
return Expression.OrElse(acc, compareExpression);
});
inExpression = inExpression ?? Expression.Constant(true);
return Expression.Lambda<Func<Product, bool>>(
inExpression,
inputExpression
);}
Calling the Expression
static void Main(string[] args)
{
var ids = new[] { 10, 20,30};
var inExpression = BuiltInExpression (ids);
EntityQuery<Product> listQuery = ProductContext.GetProductsQuery().Where(inExpression);
TestGrid.ItemsSource = ProductContext.Load(listQuery).Entities;
}