This is a migrated thread and some comments may be shown as answers.

DataServiceQuery dynamic WHERE for custom appointments

1 Answer 116 Views
ScheduleView
This is a migrated thread and some comments may be shown as answers.
Tim
Top achievements
Rank 1
Tim asked on 17 Dec 2012, 02:59 PM
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

1 Answer, 1 is accepted

Sort by
0
Tim
Top achievements
Rank 1
answered on 21 Jan 2013, 03:08 PM
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);
            }
        }
    }





Tags
ScheduleView
Asked by
Tim
Top achievements
Rank 1
Answers by
Tim
Top achievements
Rank 1
Share this question
or