I have a User that has Orders. I would like to select the User and expand Orders to include only Orders.valid == true
. Something like this:
// This is just a pseudo-query of what I want to achieve
// Note singluar 'Order.valid' also does not work
let query= new Predicate('guid', 'eq', this.user.guid).and(new Predicate('Orders.valid', 'eq', 'true');\
let users= this.uow.userSet.where(query, ['Orders']);
The where()
method is taken from the TempHire Repository and modified a little:
where(predicate: Predicate, expand: string[] = null): Promise<any[] | Entity[]> {
return new Promise<any[] | Entity[]>((resolve) => {
let query = this.baseQuery().where(predicate)
if(expand) query = query.expand(expand);
The above query does not work as a where condition cannot be applied to an Entity property that is a collection.
To solve this on the client side I have simply implemented two queries, one that fetches the user and a second that fetches the users valid orders. I would prefer to make this a single query.
I also tried to resolve this on the server side. I am using a [BreezeController] which exposes a Breeze EFContextProvider<>
following again the TempHire method of exposing each entity collection set as an IQueryable<>
. Within OrderSet()
I tried the following code:
return _efContext.Context.OrderSet.Where(o => o.valid);
However it does not seem that when a query is sent directly to the UserSet()
breeze will use the exposed OrderSet()
method to expand the User's Orders
property.
I thought about expanding the Orders
property directly within the UserSet()
to always include valid Orders (using Linq), but I don't always want Orders
returned for every query to UserSet
and I'm not sure if BreezeController will strip these unwanted includes.
Is there a better/different way to implement this either client or server side instead of simply making multiple calls to the server with individual where clauses on each Entity set?
Maybe I should create a UserOrderSet()
endpoint and call that directly when I want a User with valid Orders? Thoughts?
I figured it out!
I started reading http://briannoyesblog.azurewebsites.net/2014/02/13/passing-complex-query-parameters-with-breeze/
This guided me to create a breeze query that accepts a parameter of the Entity I want to retrieve:
[HttpGet]
[EnableBreezeQuery]
public User UserOderSet(Guid guid)
{
User user = _efContext.Context.UserSet.Where(u => u.guid == guid).Single();
List<Order> orders = _efContext.Context.OrderSet.Where(o => o.user_guid == guid && o.active).ToList();
return user;
}
Note the breeze method is returning an Entity not an IQueryable<>. This was key. Also, simply performing the EF query with a filter condition properly attaches these 'active' Orders to the User.Orders collection property.
Client site I will simply call this method directly and not require a 2nd query to load 'active' Orders.
I hope this helps somebody in the future.
BTW the more I use BreezeJS the more I absolutely love it. My hat is off to the team for their excellent work!
Thanks again,
Mike