DataServiceQuery dynamic WHERE for custom appointments

2 posts, 0 answers
  1. Tim
    Tim avatar
    41 posts
    Member since:
    Oct 2012

    Posted 17 Dec 2012 Link to this post

    I am populating my custom appointments in the following manner via DataServiceQuery

    DataServiceQuery<customAppointment> query;
     
    query = (DataServiceQuery<customAppointment>)myContenxt.customAppointmentSet
      .AddQueryOption("$select", "field1,field2,field3,field4")
      .AddQueryOption("$orderby", "field3")
       .Where<customAppointment>(a => (a.field3.Value >= start && a.field3 <= end) && (a.field4.Value == 0 || a.field4.Value == 3));

    I need to make the .Where dynamic. I have an ObservableCollection that I'm pulling information out of similar to this:

    foreach (ResourceItem r in resourceItemList)
                    {
                        if (r.IsSelected)
                        {
                            // build where clause
                        }
                    }


    I need to conditionally  add items to the where clause that are coming from this foreach loop. I'm having issues dynamically adding information to the .Where section of the DataServiceQuery.

    What is the best way to do this?

    Tim
  2. Tim
    Tim avatar
    41 posts
    Member since:
    Oct 2012

    Posted 21 Jan 2013 Link to this post

    Here's the solution for this issue:

    public static Expression<Func<ServiceAppointment, bool>> WhereClause(
                                                    IDateSpan dateSpan,
                                                    ObservableCollection<Scheduler.ViewModels.ResourceItem> resourceItemList,
                                                    string siteId)
            {
                DateTime start = dateSpan.Start;
                DateTime end = dateSpan.End;  
     
                var inner2 = PredicateBuilder.False<ServiceAppointment>();
                inner2 = inner2.Or(a => a.StateCode.Value == 0);
                inner2 = inner2.Or(a => a.StateCode.Value == 3);
     
                var outer = PredicateBuilder.True<ServiceAppointment>();
                outer = outer.And(a => a.ScheduledStart.Value >= start);
                outer = outer.And(a => a.ScheduledStart <= end);
     
                if (siteId != "" && siteId != null)
                {
                    outer = outer.And(a => a.SiteId.Id == new Guid(siteId));
                }
     
                outer = outer.And(inner2);
     
                return outer;
     
            }

    var SAWhere = WhereClause(dateSpan, resourceItemList, selectedSiteId);


    In the dataservicequery: .Where<ServiceAppointment>(SAWhere);

    Allows you to easily add conditional statements to the Where Clause.

    PredicateBuilder Class:
    public static class PredicateBuilder
        {
            /// <summary>
            /// Creates a predicate that evaluates to true.
            /// </summary>
            public static Expression<Func<T, bool>> True<T>() { return param => true; }
     
            /// <summary>
            /// Creates a predicate that evaluates to false.
            /// </summary>
            public static Expression<Func<T, bool>> False<T>() { return param => false; }
     
            /// <summary>
            /// Creates a predicate expression from the specified lambda expression.
            /// </summary>
            public static Expression<Func<T, bool>> Create<T>(Expression<Func<T, bool>> predicate) { return predicate; }
     
            /// <summary>
            /// Combines the first predicate with the second using the logical "and".
            /// </summary>
            public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
            {
                return first.Compose(second, Expression.AndAlso);
            }
     
            /// <summary>
            /// Combines the first predicate with the second using the logical "or".
            /// </summary>
            public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
            {
                return first.Compose(second, Expression.OrElse);
            }
     
            /// <summary>
            /// Negates the predicate.
            /// </summary>
            public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expression)
            {
                var negated = Expression.Not(expression.Body);
                return Expression.Lambda<Func<T, bool>>(negated, expression.Parameters);
            }
     
            /// <summary>
            /// Combines the first expression with the second using the specified merge function.
            /// </summary>
            static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
            {
                // zip parameters (map from parameters of second to parameters of first)
                var map = first.Parameters
                    .Select((f, i) => new { f, s = second.Parameters[i] })
                    .ToDictionary(p => p.s, p => p.f);
     
                // replace parameters in the second lambda expression with the parameters in the first
                var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
     
                // create a merged lambda expression with parameters from the first expression
                return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
            }
     
            class ParameterRebinder : ExpressionVisitor
            {
                readonly Dictionary<ParameterExpression, ParameterExpression> map;
     
                ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
                {
                    this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
                }
     
                public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
                {
                    return new ParameterRebinder(map).Visit(exp);
                }
     
                protected override Expression VisitParameter(ParameterExpression p)
                {
                    ParameterExpression replacement;
     
                    if (map.TryGetValue(p, out replacement))
                    {
                        p = replacement;
                    }
     
                    return base.VisitParameter(p);
                }
            }
        }





  3. DevCraft banner
Back to Top