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!
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!
.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};