RIA-Services - как сделать WhereOr или использовать конструкцию в стиле IN - PullRequest
1 голос
/ 28 августа 2010

Я использую SL 4, Службы RIA WCF против Entity Framework 4.0. У меня есть объект Entity, который имеет строковое поле Status. У меня есть экран поиска, где мне нужно отобразить результаты, которые имеют StatusA или StatusB. Я изо всех сил пытаюсь найти способ указать запрос на стороне клиента, который определяет набор состояний, которые должны быть сопоставлены. Если бы я написал в SQL то, что я хочу, он бы выглядел примерно так:

select * from Visit where Status in ('StatusA', 'StatusB');

На стороне клиента, кажется, что это просто для цепочки Где методы для эффекта WhereAnd:

        var query = this.PqContext.GetVisitsQuery();

        if (!string.IsNullOrEmpty(this.PracticeName))
        {
            query = query.Where(v => v.PracticeName.ToUpper().Contains(this.PracticeName.ToUpper()));
        }

        if (this.VisitDateAfter.HasValue)
        {
            query = query.Where(v => v.VisitDate > this.VisitDateAfter);
        }

        if (this.VisitDateBefore.HasValue)
        {
            query = query.Where(v => v.VisitDate < this.VisitDateBefore);
        }

Однако я не могу найти простой способ выполнить операцию в стиле WhereOr. Я пробовал это:

        var statuses = new List<string>();

        if (this.ShowStatusA)
        {
            statuses.Add("StatusA");
        }

        if (this.ShowStatusB)
        {
            statuses.Add("StatusB");
        }

        if (statuses.Any())
        {
            query = query.Where(BuildContainsExpression<Visit, string>(e => e.Status, statuses));
        }

Где BuildContainsExpression выглядит так:

        private static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
    {

        if (null == valueSelector)
        {
            throw new ArgumentNullException("valueSelector");
        }

        if (null == values)
        {
            throw new ArgumentNullException("values");
        }

        ParameterExpression p = valueSelector.Parameters.Single();
        if (!values.Any())
        {
            return e => false;
        }

        var equals =
            values.Select(
                value =>
                (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));

        var body = equals.Aggregate<Expression>(Expression.Or);

        return Expression.Lambda<Func<TElement, bool>>(body, p);
    }

Но это выдает «Побитовые операторы не поддерживаются в запросах». исключение. Есть какие-нибудь подсказки? Есть ли альтернативный способ построить дерево выражений, которое работает здесь, или мне нужно передать все параметры на сервер и использовать там выражение BuildContainsExpression?

Ваше время и ваше руководство высоко ценится.

1 Ответ

1 голос
/ 29 августа 2010

Вы можете создать метод запроса, такой как следующий, в вашей доменной службе:

GetVisitsByStatus(string[] statusList) {
  // create the LINQ where clause here
}

А затем с клиента вызовите context.GetVistsByStatusQuery (string []).

Notвесь LINQ может (или даже может) отображаться через URL, поэтому всегда есть случаи, когда вам нужно использовать простые параметры, а средний уровень создает выражения LINQ, которые в конечном итоге определяют запрос, который идет к внутренним данныммагазин.

Надеюсь, что поможет.

...