In this topic we explore Breeze query features and techniques in depth.
If a query completely misbehaves, take a look at the “Query result debugging” topic.
This page is currently a framework for topics and is nowhere near complete. Eventually this page will cover:
Please consult the API documentation for the following related classes:
The QueryTests module in DocCode sample demonstrates many of the techniques covered in this topic.
This page is under construction. The following is a grab-bag of details concerning the points just enumerated.
Often the method on the server does not recognize OData URI query syntax but it does take other parameters passed in the query string of the request.
You can query these endpoints by adding the .WithParameters(...)
clause to your query.
This is probably how you will query servers that are not written with .NET technologies.
Brian Noyes has an excellent blog post describing WithParameters
queries in great detail. His examples are in JavaScript but the same API is present in the Breeze.Sharp product.
Web API Example:
Client
var query = EntityQuery.from("EmployeesByFirstName")
.WithParameter("firstName", "Fred");
Server
[HttpGet]
public IQueryable<Employee> EmployeesByFirstName(string firstName) {
return ContextProvider.Context.Employees.Where(e => e.firstName == firstName);
}
Notice that we pass the parameter names and their values. The spelling and capitalization of the parameter name may be important. Breeze constructs the URL with these names as you spell them, expecting the server to correlate the names with parameters of the method at the target endpoint. In our example, “firstName” matches the parameter name of the EmployeesByFirstName
method on the server.
Obviously you could have written this as a normal Breeze query but we trust you get the idea.
Web API assumes that data for non-simple parameter types will be in the body of the request. GET requests don’t have bodies. The Breeze client serialized the array values into the query string of the request URI. This attribute tells the Web API to bind the parameter to those array values in the URI.
A query typically returns all entities that satisfy the filter criteria in your Where
clause(s). It could return a lot of data … perhaps more data than you need or want right now.
You can ask for a smaller “page” of data instead by specifying the number of items to keep (Query.Take(10)
). This is your “page size”.
To skip a few pages before getting to the page you want, do this:
query.OrderBy(something).Skip(pageSize * pageSkip).Take(pageSize)
You can append
Take
to any query but your query must have anOrderBy
clause before you can addSkip
. You can useSkip
withoutTake
… but why would you?
You can get a count of the entities that satisfy your filter criteria at the same time you get a page of results by adding the .InlineCount()
clause to the query. When you add the InlineCount()
clause to the query you will actually be changing the return type that the query returns when executed. It is still an IEnumerable
Let’s put these thoughts together:
var products, inlineCount, resultCount, query;
var pageSize = 5;
var pageSkip = 1;
query = new EntityQuery<Product>()
.Where(p => p.ProductName.StartsWith("C"))
.OrderBy(p => p.ProductName)
.Skip(pageSize * pageSkip) // skip a page
.Take(pageSize) // take a page
.InlineCount();
var products = await myEntityManager.ExecuteQuery(query);
// 'products' implements IEnumerable<Product>
// and contains page of products beginning with 'C'
// but it also implements IHasInlineCount via an explicit interface.
// hence the need to cast.
var inlineCountInfo = (IHasInlineCount) products;
var inlineCount = inlineCountInfo.InlineCount; // count of products beginning with 'C'
resultsCount = products.length; // 0 <= resultsCount < pageSize
Breeze does not yet support aggregate queries (count, sum, average, etc.). But we can get the count of a query without retrieving any actual data using the “Take(0), InlineCount()” trick:
var inlineCount, resultCount, query;
query = new EntityQuery<Product>()
.Where(p => p.ProductName.StartsWith("C"))
.Take(0).InlineCount();
var results = await myEntityManager.ExecuteQuery(query);
resultsCount = results.Count(); // 0
inlineCount = ((IHasInlineCount) results).InlineCount; // count of products beginning with 'C'
The QueryOptions
object defines two strategies that guide the EntityManager’s processing of a query.
The FetchStrategy
determines the query target (server or cache).
The MergeStrategy
tells Breeze how to merge raw entity query data into cache when an entity with that key is already in cache.