RIA Services : Include with Select(Many) not Worki

2019-05-24 15:04发布

问题:

I have two entity types: Document (has a Customer) and Customer (has a collection Documents)

My query is to get documents for a customer based on either the customer's name or number.

The query looks like this:

public IQueryable<Document> GetCustomerDocuments(DateTime startDate, DateTime endDate, string filterText)
{
    return this.ObjectContext.Customers
              .Where(c => c.CustomerName.Contains(filterText) || c.CustomerNumber.Contains(filterText))
              .SelectMany(c => c.Documents)
              .Where(d => d.Date >= startDate && d.Date <= endDate);
}

When the query returns, I want it to include BOTH the Document and Customer entities....

I have tried everything I can think of including Include("Documents.Customer"),Include("Customer"),etc.

I definitely have the IncludeAttribute set in the metadata.

Thoughts? Is this even possible?

Thanks!

回答1:

Instead of using projection and SelectMany, I wrote a LINQ query using a join:

        var v = from cust in (from c in this.ObjectContext.Customers
                where  (c.CustomerName.Contains(filterText) || c.CustomerNumber.Contains(filterText))  select c)
                join doc in this.ObjectContext.Documents on cust.CustomerNumber equals doc.CustomerNumber
                where doc.Date >= startDate && doc.Date <= endDate
                select doc;
        return ((ObjectQuery<Document>)v).Include("Customer").AsQueryable<Document>();

This solves the problem!



回答2:

.Include works off ObjectQuery, and it's effect will be undone when adding any custom projection. You can try the following options:

Rewrite the query in terms of Document:

return this.ObjectContext.Documents.Include("Customers")
          .Where(d => d.Customers.Any(c => 
                                      c.CustomerName.Contains(filterText) 
                                   || c.CustomerNumber.Contains(filterText))
          .Where(d => d.Date >= startDate && d.Date <= endDate);

This may or may not work, and may or may not generate decent sql; to be tested.

Another possibility is to define a DTO object

class CustomerDocument
{
   public Customer {get;set;}
   public Document {get;set;}
}

Then your query becomes:

return from c in this.ObjectContext.Customers
       from d in c.Documents
       where (c.CustomerName.Contains(filterText) 
          || c.CustomerNumber.Contains(filterText))
           && d.Date >= startDate && d.Date <= endDate
       select new CustomerDocument {Customer = c, Document = d};