locked
Creating a search filter? RRS feed

  • Question

  • Hi,

    I´m trying to create a search function in a WPF app using WCF DataServices.

    I have an entity (server side) that I need to add a filter command for searching.

    public class Searchable
    {
      public string State {get;set;}
      public DateTime DateCreated {get;set;}
      public int CustomerId {get;set;}
    } 
    

    I need to create a search function client side to be able to  search the db using all three of the properties of the searchable class.

    I have a UI that allows the user to select from States, Customers and a date range to filter by and from the users selection I need to construct a query to filter the results.

    What strategy should I use for the query construct?

    AddQueryOption seem like the right thing to do but I can´t get it to work correctly.

    Can someone give me an example of how to create a query based on the params given for all/any of the provided params:

    int? customerId,

    DateTime FromDate

    DateTime ToDate

    string State

    I need to construct the query at runtime based on the selected filters where all but the date range are optional.


    Thanks, nisbus
    Monday, November 8, 2010 12:58 AM

Answers

  • Hello,

    The right strategy is to construct Linq Where expressions dynamically, and then input the expression into a DataServiceQuery instance created by the DataServiceContext class.

    You cannot input $filter parameter by using AddQueryOption, this API is meant to be used for non-data-service-standard query constructs.

    Example below:

    DataServiceContext ctx = new DataServiceContext(new Uri("http://localhost"));
    
    // input parameter: Searchable p0
    ParameterExpression p0 = Expression.Parameter(typeof(Searchable), "p0");
    
    // p0.State
    Expression stateMemberAccess = Expression.MakeMemberAccess(
      p0, 
      typeof(Searchable).GetMember("State", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).Single());
    
    // p0.DateCreated
    Expression dateMemberAccess = Expression.MakeMemberAccess(
      p0,
      typeof(Searchable).GetMember("DateCreated", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).Single());
    
    // p0.State == "WA"
    Expression equalsExpr = Expression.MakeBinary(ExpressionType.Equal, stateMemberAccess, Expression.Constant("WA"));
    
    // p0.DateCreated > 2010/06/06
    Expression lessThanExpr = Expression.MakeBinary(ExpressionType.GreaterThan, dateMemberAccess, Expression.Constant(new DateTime(2010, 06, 06)));
    
    // p0.State == "WA" && p0.DateCreated > 2010/06/06
    Expression queryExpr = Expression.MakeBinary(ExpressionType.And, equalsExpr, lessThanExpr);
    
    // p0 => p0.State == "WA" && p0.DateCreated > 2010/06/06
    var lambda = Expression.Lambda<Func<Searchable, bool>>(queryExpr, p0);
    
    var q = ctx.CreateQuery<Searchable>("EntitySet").Where(lambda);
    

    q should now be translated to:

    http://localhost/EntitySet()?$filter=(State eq 'WA') and (DateCreated gt datetime'2010-06-06T00:00:00')

     

    You can take the above code, refactor it a bit and use it to generate dynamic filter expressions based on UI input.

     

    Regards,

    PQ


    Peter Q. http://blogs.msdn.com/peter_qian
    Monday, November 8, 2010 9:22 PM
    Answerer