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:
- 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).
- Asynchronously issues an HTTP GET to the server and expects a JSON payload in the returned HTTP response body
- 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.
We focus on making sure your data is secure.
Together we review all your data sources and current storage capabilities.
This includes dealing with data in motion, data at rest and long-term archiving.
Put the right infrastructure in place.
Together we carefully plan out all aspects of your data protection including archiving, backup, and how to recover it.
Secured end-to-end.
We take into consideration more than the physical storage and look at the entire solution including the network and encryption needs.
Actively monitored 24x7x365
We make sure there are no surprises by actively tracking utilization and failures to keep your data and applications peforrming at their best.
More than technology
All Atmosera customers benefit from processes, policies, training and 24x7x367 technical resources.
Our customers have the peace of mind of knowing an industry expert has performed a thorough risk assessment,
identified a remediation plan and provided ongoing audit support to ensure customers stay protected.
Best of all, we understand this level of service is — and will continue to be — required year after year.
We always implement networks which deliver
better security and usability.
All our deployments take into consideration the end-to-end solution and
we secure all aspects of the network and connectivity.
- Defense in Depth – Our approach offers a flexible and customizable set of capabilities based on enterprise-grade standards for performance, availability, and response.
- WANs, MANs, LANs, and VPNs – We provide comprehensive networking and high-speed connectivity options from Wide Area Networks (WAN), Metropolitan Area Networks (MAN) and Local Area Networks (LAN), as well as managed Virtual Private Networks (VPNs) and firewalls.
- Stay current – We can be counted on to deliver proactive testing and the most secure network protocols.
- Reduce vulnerabilities – We help your team leverage advanced security features coupled with relentless vigilance from trained experts.