Here's an interesting problem that I hope someone can lend a hand with.
I have a DomainService class with the following query:
[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)
});
}
This works BUT I really need the paging/sorting information passed from the Silverlight client to be applied before enumeration happens in the line calling .ToArray()
The client side is using the DomainDataSource Silverlight control.
How can I achieve this?
The easiest way is adding paging/sorting/filtering parameters to the method arguments list and adding corresponding LINQ query operators to your data context query in the service method. However, in this case you'll loose client-side IQueryable
features. I mean, client's queries will reach only the application server, but won't get to the database. And you'll need some layer between the DomainContext
and the UI: DomainDataSource
is not likely to work.
Exposing the results of the query as IQueryable
using AsQueryable()
won't help since expression trees will be unconditionally compiled into code in order to execute your LINQ-to-Objects operators.
Somewhat harder option is using arguments as in first case together with writing your own IQueryable
wrapper over the client-side query object. This wrapper would extract parameters from query expressions and pass them to the service as method arguments. Well, I'd only try this if I had enough spare time.
Another difficult way is doing analogous thing server-side. It's possible to get an IQueryable
object that has the expression tree passed from client in a DomainService
. You'll need to override the DomainService.Query
method. Then you'll be able to extract part of the query expression that relates to paging/sorting, save it to a field and then apply to the database query. However, Query
method is single for all methods in a given DomainService
. Therefore, you'll probably end with a big table method that decides what to do for each of the service query methods. Needless to say, the service will become very difficult.
To conclude, I strongly recommend you the first option.