UPDATE: I recently published a WintellectNow course (Getting Started with Breeze.js) that goes into more depth using Breeze in the context of an AngularJS app.  Use code NSTIEGLITZ-13 for a free 2 week WintellectNow trial.

BreezeJS is a JavaScript library to help manage data in rich client web applications.  It’s especially useful in Enterprise and Line of Business (LOB) applications where users often query, save, and delete large amount of data.  Using the BreezeJS library is a joy to work with and feels like Entity Framework on the client.  BreezeJS provides:

  • Rich “LINQ like” Querying
  • Change Tracking
  • Entity Relationship Navigation
  • Client Caching
  • Validation
  • Offline Saving
  • Tight Integration with Web API and Entity Framework (neither are required)
  • Access to any RESTful API using custom metadata
  • Integration with JavaScript libraries/Frameworks like AnguarJS and KnockoutJS

 

In future posts I will expand on the entire feature set.  In this post, I’ll focus on the Rich “LINQ like” Querying.

LINQ like Querying

Advanced querying is probably the most compelling case for BreezeJS.  If you’re familiar with Entity Framework, querying in BreezeJS will feel quite intuitive.  With Breeze, you can easily write queries that filter, sort, page, project data, and even eager load relationships.

Filtering

Here is a simple query that filters a list of customers by Company Name:

var query = breeze.EntityQuery.from('Customers')
    .where('CompanyName', FilterQueryOp.Contain, 'Around');

The EntityQuery method creates a query which can be used against remote or local data stores.  The where clause applies the predicate as a filter (in this case – company name).  I’m using the FilterQueryOp “enum” (JavaScript doesn’t really have enums) which allows you to specify various predicates like Contains, Equals, LessThan, etc.  Check the full list here.

It is also possible to build up queries by chaining predicates.  This is useful, for example, if you have a search page with many optional search parameters.  In this example, I chain two predicates using and:

var query = breeze.EntityQuery.from('Customers');

var p1 = breeze.Predicate.create('ContactTitle', 'Contains', 'Rep');
var p2 = breeze.Predicate.create('City', 'Eq', 'London');
var pred = breeze.Predicate.and([p1, p2]);

query = query.where(pred);

I’ve used the predicate technique before with Entity Framework on the service tier; I’m glad to see a similar technique on the client.

Just to show you what’s possible, below is an example of a pretty advanced query.  It retrieves a list of all customers who have placed any orders with order details that have a quantity greater than 40:

var query = breeze.EntityQuery
     .from('Customers')
     .where('Orders', 'any', 'OrderDetails', 'all', 'Quantity', '>', 40);

As seem, it’s easy to filter deep into the object graph.

Now you have seen how to build a query, here is how you execute a query:

manager.executeQuery(query)
            .then(successCalllback)
            .fail(failCallback)
            .fin(finallyCallback); //execute the query and resolve to a promise

When you call executeQuery(query), Breeze will:

  1. Generate a URL which looks something like this:
    • http://localhost:50283/breeze/Customer/Customers?$filter=Orders/any(x1: x1/OrderDetails/all(x2: x2/Quantity gt 40)
    • Notice the where clause from the query has been converted into the URLs query string (a la ODATA).
  2. Asynchronously issues an HTTP GET to the server and expects a JSON payload in the returned HTTP response body
  3. Assuming the call was a success, Breeze reshapes the JSON data into Breeze entities and merges those entities into the local cache.  It then resolve the promise, allowing you, the developer, to handle the returned data via the successCallback.

 

Thanks Breeze – that was awesome!  Now in the successCallback I can bind the data to a view, log any errors in my failCallback, and do any cleanup in the fin callback.

Sorting

Sorting in BreezeJS is super straight forward and pretty powerful.  Check out this example from the BreezeJS documentation:

// Products sorted by their Category names, then by Product name (in descending order)
var query = breeze.EntityQuery.from('Products')
    .orderBy('Category.CategoryName, ProductName desc');

The code is pretty self explanatory.  It demonstrates that you can sort by related properties either ascending or descending.  As an alternative to adding the desc text, there is also an orderByDesc method.

// Products in descending name order (version 2)
var query = breeze.EntityQuery.from('Products')
    .orderByDesc('ProductName');

Paging

Breeze provides the ability to page data using the skip and take methods as demonstrated in this query:

// Get the 3rd page of 5 Customers
// by skipping 10 Customers and taking the next 5
var query = breeze.EntityQuery.from('Customers')
    .orderBy('ContactName')
    .skip(10)
    .take(5);

Projecting

If you don’t need all properties on an entity, you can use projection to retrieve only the relevant properties.  For example, this query would allow you to wire up a view which lists a customer’s contact name and company name:

//We only need the company name and contact name
var query = breeze.EntityQuery.from('Customers')
    .select('CompanyName, ContactName');

You can also project properties from related entities.  For example, this query retrieves a list of customers who placed orders with freight charges over $500:

var query = breeze.EntityQuery.from('Orders')
    .where('Freight', FilterQueryOp.GreaterThan, 500)
    .select('Customer.CompanyName');

Eager Loading

If you know you need related entities up front, it’s often a good idea to grab all of the data in a single call.  Maybe you need to build a view which displays a list of customers in Mexico and their related orders.  This query eagerly loads the customer’s orders:

var query = breeze.EntityQuery.from('Customers')
    .where('Country', 'eq', 'Mexico')
    .expand('Orders');

How easy is that?!

Conclusion

If you haven’t yet, go check out the BreezeJS documentation and download some of the samples.  Stay tuned for an upcoming BreezeJS video I’ll publish on WintellectNow.