RIA-Services - 如何WhereOr或使用IN样式构造

发布于 2024-09-16 11:09:17 字数 2449 浏览 2 评论 0原文

我正在针对 Entity Framework 4.0 使用 SL 4、WCF RIA 服务。我有一个实体 Visit,它有一个字符串 Status 字段。我有一个搜索屏幕,我需要在其中显示具有 StatusA 或 StatusB 的结果。我正在努力寻找一种方法来指定客户端查询,该查询指定应匹配的状态集合。如果我要在 SQL 中编写我想要的内容,它看起来会像这样:

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

客户端,它似乎可以直接链接Where 方法来实现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?

非常感谢您的时间和指导。

I am using SL 4, WCF RIA Services against Entity Framework 4.0. I have an Entity, Visit, that has a string Status field. I have a search screen where I need to display results that have StatusA or StatusB. I am struggling to find a way to specify a client-side query that specifies a collection of statuses that should be matched. If I was to write what I want in SQL it would look something like:

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

Client side, it appears to be straightforward to chain Where methods for a WhereAnd effect:

        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);
        }

However, I can't seem to find a straightforward way to do a WhereOr style operation. I have tried this:

        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));
        }

Where BuildContainsExpression looks like:

        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);
    }

But this throws a "Bitwise operators are not supported in queries." exception. Any clues? Is there an alternative way to build an expression tree that works here or do I need to pass all the parameters over to the server and use the BuildContainsExpression there?

Your time and your guidance are much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

逐鹿 2024-09-23 11:09:17

您可以在域服务中创建如下查询方法:

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

然后从客户端调用 context.GetVistsByStatusQuery(string[])。

并非所有 LINQ 都(甚至可以)通过 URL 公开,因此在某些情况下您总是需要使用简单参数,并让中间层构造 LINQ 表达式,最终定义发送到后端的查询数据存储。

希望有帮助。

You can create a query method such as the following in your domain service:

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

And then from the client, call context.GetVistsByStatusQuery(string[]).

Not all of LINQ is (or even can) be exposed over the URL, so there are always cases where you need to use simple parameters, and have the middle tier construct the LINQ expressions that eventually define the query that goes to the back-end data store.

Hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文