使用EF Projection的RIA Services DomainService查询调用方法并仍然允许可组合的分页/排序

时间:2011-12-02 15:33:35

标签: asp.net silverlight linq linq-to-entities wcf-ria-services

这是一个有趣的问题,我希望有人可以帮忙。

我有一个DomainService类,其中包含以下查询:

    [Query]
    public IEnumerable<BatchResult> GetBatchResults(int batchId)
    {
        return ObjectContext.BatchQueries
            .Include("BatchTCResults")
            .Include("BatchANFResults")
            .Where(x => x.BatchId == batchId)
            .Where(x => x.BatchTCResults.Any() || x.BatchANFResults.Any())
            .ToArray() // enumerate because projection calls a method that EF will poop it's pants on
            .Select(x => new BatchResult
            {
                BatchQueryId = x.Id,
                Route = x.Routing,
                Account = x.Account,
                Amount = x.Amount,
                CheckNumber = x.CheckNumber,
                Severity = BatchResult.DetermineOverallSeverity(x)
            });
    }

这可行但是我真的需要从Silverlight客户端传递的分页/排序信息在枚举发生在调用.ToArray()

的行中之前应用

客户端正在使用DomainDataSource Silverlight控件。

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:3)

最简单的方法是将分页/排序/过滤参数添加到方法参数列表中,并将相应的LINQ查询运算符添加到服务方法中的数据上下文查询中。但是,在这种情况下,您将丢失客户端IQueryable功能。我的意思是,客户端的查询只会到达应用程序服务器,但不会到达数据库。并且您需要DomainContext和用户界面之间的某个图层:DomainDataSource不太可能有用。

使用IQueryable将查询结果公开为AsQueryable()将无济于事,因为表达式树将无条件地编译为代码以执行LINQ-to-Objects运算符。

在第一种情况下使用参数以及在客户端查询对象上编写自己的IQueryable包装器有点困难。此包装器将从查询表达式中提取参数,并将它们作为方法参数传递给服务。好吧,如果我有足够的业余时间,我只会尝试这个。

另一个困难的方法是在服务器端做类似的事情。可以在IQueryable中获取一个DomainService对象,该对象具有从客户端传递的表达式树。您需要覆盖DomainService.Query方法。然后,您将能够提取与分页/排序相关的部分查询表达式,将其保存到字段,然后应用于数据库查询。但是,Query方法对于给定DomainService中的所有方法都是单一的。因此,您可能会以一个大表方法结束,该方法决定如何为每个服务查询方法执行操作。不用说,服务将变得非常困难。

总而言之,我强烈建议您选择第一个选项。