Search code examples
breeze

Breeze query to include filtered related entities


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?


Solution

  • 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