Below are the release notes for the older 1.5.x and 1.4.x releases.
There are two new package names: breeze-client and breeze-client-labs.
This is a breaking change for every app that loaded Breeze (or Breeze Labs) through the breezejs bower or npm packages. You'll want to update your bower.json and package.json files accordingly and update your index.htm. files to load the scripts that you need from their new locations. The former breezejs packages have been retired and are frozen at BreezeJS version 1.5.2.
We made this change because:
The breeze-client package has three levels:
breeze.debug.js
build
breeze.debug.js
breeze.min.js
breeze.base.debug.js
breeze.base.min.js
adapters
... all core adapters ...
BeforeSaveEntities
to add and remove EntityInfos, involving AutoGeneratedKey values. (F2311)New predicate operator: ‘in’. This operator can be used to query if a property has a value that is among a list of specified values: Example:
var countries = ['Austria', 'Italy', 'Norway']
var query = EntityQuery.from("Customers")
.where("country", 'in', countries);
resolveProperty
method is now defined for NavigationProperties
as well as DataProperties
. (D2634)EntityManager
would only raise the first EntityStateChange
event for each entity. (D2635)includeDeleted
flag is set to true). (D2636)rejectChanges
on a entity with collection of complex types would ‘double’ the complexType collection.(D2639)entityChanged
event was not firing reliably when deleting an entity. (D2640).NamingConvention
is in play.EnableBreezeQuery
attribute to support WebApi 2.2. This replaces and supersedes the BreezeQueryable
attribute which is deprecated.EntityManager.saveChanges
sends to the server.D2613 - Corrected truncation of unmapped numeric properties to Integer when retrieved from server.
D2574 - Attention OData JsonResultsAdapter authors. The entityAspect.extraMetadata
is now preserved by exportEntities
. While fixing, we changed the related property of the JsonResultsAdapter.visitNode
result from result.extra
to result.extraMetadata
. Correct your JsonResultsAdapter accordingly.
D2602 - “After save the entityAspect.propertyChanged
event is no longer raised for a property that was changed on the server”. Actually propertyChanged is still raised in that situation. But Breeze only raises the event once. The value of the propertyChangedArgs.propertyName
is null
which means “many properties changed”. This behavior was described in the API documentation. Previously Breeze raised a separate event for each changed property individually for every merged entity … which may have been convenient but was not correct . If you relied on the (incorrect) behavior, you will experience the proper behavior as a breaking change.
requestInterceptor
to enable fine-tuning of a Breeze AJAX request such as timeout and mock response. See the new documentation, “Controlling AJAX calls”.EntityQuery.fromEntityKey
specifically targets the EntityType
of the EntityKey
and casts query results into that EntityType
.
New or changed in Breeze Labs
Breeze AngularJS Service, a new breeze.angular.js module that configures your Breeze/AngularJS client app for AngularJS in “AngularJS-style”. Sets the right ‘model library’, $q
for promises, and $http
for ajax calls. It has its own nuget package.
getEntityGraph extends EntityManager
so you can retrieve a root entity and its related entities from cache as an array. Read why and how in the breeze labs documentation.
metadata-helper (updated) library to make hand-coding Breeze metadata in JavaScript a bit easier. Now a nuget package.
EdmBuilder, a tiny C# class that generates Breeze-compatible metadata for a Web API OData backend. See the Web API OData sample.
+ **SharePoint 2013 OData DataService Adapter**, included in the SharePoint/AngularJS package, this is independent of AngularJS and therefore suitable for a Breeze application that doesn't use AngularJS. Best acquired [from nuget](https://www.nuget.org/packages/Breeze.DataService.SharePoint/).
+ **breeze.directives.validation** is in the middle of a rewrite to enable richer options for developer configuration. The code has changed, the behavior ... not yet (at least not intentionally).
+ **AngularJS.MidwayTester** - a [nuget package](https://www.nuget.org/packages/Angular.MidwayTester/), delivering [Matias Niemelä's AngularJS test library](https://github.com/yearofmoo/ngMidwayTester) (with his kind permission) for async testing. Great for testing that your Breeze client is talking to your server in the ways you expect.
Deprecated in Breeze Labs
$expands
on subclasses.invForeignKeyNamesOnServer
to metadata.NHContext
method signatures from private to protected to ease overriding of SaveChangesCore
by subclasses.Breeze previously required that any single quotes within a query string be manually escaped within an EntityQuery. This is no longer required ( and will in fact cause the query to fail).
// Old Code
var q = EntityQuery.from("Employees").where("lastName", "contains", "O''Malley");
// should be converted to
var q = EntityQuery.from("Employees").where("lastName", "contains", "O'Malley");
For more info see Entity Query Any/All conditions
An EntityQuery.noTracking method has been added to allow EntityQueries to return simple JavaScript objects instead of Breeze entities. The method accept a single optional boolean parameter that determines whether or not the noTracking capability should be enabled. If this parameter is omitted, true is assumed.
With ‘noTracking’ enabled, the results of the query will not be coerced into entities but will instead look like raw JavaScript projections. i.e. simple JavaScript objects. However, the following “entity” services will still be performed
a) graph cycle resolution
b) property renaming
c) datatype coercion
Note that any EntityQuery.expand will still work with ‘noTracking’ queries and will return parent entities with attached children all as simple js objects.
These objects will not be added to the EntityManager and will not be observable. However, as mentioned above, breeze cycle management and data type transformations will still occur. Because they skip the cache-merging step, such queries might materialize significantly faster than a corresponding query without the ‘noTracking’ option. Your mileage may vary.
Example:
var query = EntityQuery
.from("Orders")
.where("customer.companyName", "startsWith", "C")
.expand("customer")
.noTracking();
myEntityManager.executeQuery(query).then(function (data) {
...
});
Entity graphs are now supported when passing ‘initialValues’ to the EntityManager.createEntity, EntityManager.attachEntity, and EntityType.createEntity methods.
This facility may be used in conjunction with the new EntityQuery.noTracking method when there is a need to convert a subset of the results of a noTracking query into entities and attach them to an EntityManager. For example:
var empType = myEntityManager.metadataStore..getEntityType("Employee");
var q = EntityQuery.from("Employees")
.expand("orders")
.noTracking()
.using(myEntityManager);
q.execute().then(data) {
var rawEmps = data.results;
emps = rawEmps.map(function (rawEmp) {
emp = empType.createEntity(rawEmp);
// emp has an entityAspect at this point but is not yet attached.
empx = myEntityManager.attachEntity(emp, EntityState.Unchanged,MergeStrategy.SkipMerge);
// empx may NOT be the same as emp because of the possibility that an emp
// with the same key already exists within the EntityManager.
return empx;
});
});
The export/import features added in this release are documented in Exports and Imports.
The EntityManager.exportEntities method now has a second boolean parameter, includeMetadata
. It is optional and defaults to ‘true’. Set this second parameter to false
if you want to exclude metadata. Example:
myEntityManager.exportEntities(entitiesToExport, false); // export without metadata
Entities exported without metadata must be re-imported into an EntityManager
that already contains the matching metadata or else an exception will be thrown.
The EntityManager.importEntities method has been extended to accept the import of exported entities without metadata. The ‘config’ parameter to this method has also been extended with an additional optional metadataVersionFn property. The property allows a developer to ‘inject’ a custom function to be executed as the first step of the import process to determine if the imported data is ‘correct’. For example
myEntityManager.importEntities(exportedEntities, {
mergeStrategy: breeze.MergeStrategy.PreserveChanges,
metadataVersionFn: function (cfg) {
if (myEntityManager.metadataStore.name != cfg.metadataStoreName) {
throw new Error("Incorrect store name")
}
if (breeze.metadataVersion != cfg.metadataVersion) {
throw new Error("Incorrect metadata version")
}
}
}); <a name="name-property"></a>
An additional name property has been added to the MetadataStore. This allows a developer to ‘name’ a collection of metadata. This name is automatically included as part of the package resulting from any exportEntities method call and can be accessed during the execution of any importEntities call via the metadataVersionFn described above. The name property may be set via the MetadataStore.setProperties method.
myEntityManager.metadataStore.setProperties({
name: "Foo-17"
});
The serialization features added in this release are documented in Entity Serialization.
When serializing data from the Breeze client to either the server or to an exported string, Breeze automatically ensures that exceptions do not occur during the serialization process. In practice this means ensuring that any ‘unmapped’ properties serialize ‘correctly’. It does this according to the following rules:
1) If the object being serialized has a property named toJSON whose value is a function, then the toJSON method customizes the JSON serialization behavior: instead of the object being serialized, the value returned by the toJSON method when called will be serialized. (This is the same function and behavior as is used by the JSON.stringify method).
2) Functions are never serialized unless they have a toJSON function property.
3) Objects that contain cycles have cyclical properties stubbed out at the point where a previously serialized node is encountered. As with functions, this behavior can be mediated with a toJSON implementation.
A new “serializerFn” property has been added to both the MetadataStore and the EntityType classes. This property, if present, mediates the entity serialization process. Note that the serialization rules from the item above are still applied AFTER the serializerFn executes.
The ‘serializerFn’ takes two arguments: a DataProperty, and a value. The return value of the function determines what gets serialized for the specified property. If an ‘undefined’ is returned then the serialization of that property is suppressed.
The MetadataStore.setProperties method and the EntityType.setProperties methods are used to set this property.
As as example, the following code suppresses the serialization of all ‘unmapped’ properties.
myEntityManager.metadataStore.setProperties({
serializerFn: function (dataProperty, value) {
return dataProperty.isUnmapped ? undefined : value;
}
});
None
Support for Microsoft VS 2013, ASP.NET Web API 2, and Entity Framework 6. This release primarily involves 3 new dlls and 4 new Nuget packages that together support Web API 2 and Entity Framework 6. All older Breeze packages are also still supported.
The Breeze JavaScript client (1.4.5) will work with both the new Web API 2 dlls as well as the old ones.
New dlls
New Nuget packages
To convert a (legacy) Breeze project to Breeze ASP.NET Web API 2 and Entity Framework 6 project involves
Added an AngularJS Ajax adapter. The new adapter can be initialized by calling
breeze.config.initializeAdapterInstance("ajax", "angular");
The default Breeze Ajax adapter is still jQuery. The new angular adapter should be used if you do not want to use jQuery at all within an AngularJS application.
This adapter makes use of AngularJS’s $http to perform any Ajax calls. By default, Breeze will create isolated $http and $rootScope instances for these calls in order to avoid AngularJS side effects. If you want to provide your own $http instance instead you can use the setHttp method on the adapter instance itself.
var instance = breeze.config.initializeAdapterInstance("ajax", "angular");
instance.setHttp($http);
This addition also involved making a “minor” breaking change to the AJAX adapter requirements and base implementation so as to not depend on the jQuery.AJAX API. (see Breaking changes below)
The Ajax adapter api was changed to allow support for Ajax adapters that are not jQuery “like”. This change should NOT affect any applications unless they subclassed the existing Ajax adapter or called into it directly. Applications that called methods on the EntityManager or the MetadataStore are NOT affected by this change.
The change involved the config parameter of API’s “Ajax” method.
adapter.ajax(config);
The change was to the success and error callback function properties of the config object. These used to be defined as follows ( following the jQuery API).
config.success := function (data, textStatus, XHR);
config.error := function (XHR, textStatus, errorThrown);
These two properties are now defined as
config.success := function (httpResponse);
config.error := function (httpResponse);
where the httpResponse object consists of the following properties and methods.
httpResponse.data – {string|Object} – The response body
httpResponse.status – {number} – HTTP status code of the response.
httpResponse.getHeaders(headerName) - Header getter function - a null headerName will return all headers.
httpResponse.error - {Error | String} - an optional error object
httpResponse.config - {Object} The configuration object that was used to generate the request.
This change has also made it much easier to create a stub or mock Ajax adapter.
Complex objects are now supported in the EntityQuery.withParameters method.
Client code
var query = EntityQuery.from("SearchCustomers")
.withParameters( { CompanyName: "A", ContactNames: ["B", "C"] , City: "Los Angeles" } );
Server Code
public class CustomerQBE {
public String CompanyName { get; set; }
public String[] ContactNames { get; set; }
public String City { get; set; }
}
[HttpGet]
public IQueryable<Customer> SearchCustomers([FromUri] CustomerQBE qbe) {
var ok = qbe != null && qbe.CompanyName != null & qbe.ContactNames.Length > 0 && qbe.City.Length > 1;
if (!ok) {
throw new Exception("qbe error");
}
// do something interesting with qbe ...
}
Support for NHibernate - (this is a BETA feature). A sample is available now.
The breakup of the Breeze.WebApi dll into several assemblies means that for any Entity Framework dependent Breeze server side projects.
This means that if you were using Breeze with the Entity Framework
using Breeze.WebApi;
must be replaced with
using Breeze.WebApi;
using Breeze.WebApi.EF;
The Predicate.create method and the Predicate constructor have been extended so that both will now also accept a standard ‘OData’ query clause. OData clauses may also be combined with any standard query clauses. However, any EntityQuery containing an explicit OData clause will only be executable remotely, i.e. you cannot execute these queries locally.
var query = breeze.EntityQuery.from("Employees")
.where("EmployeeID add ReportsToEmployeeID gt 3");
The Predicate.and and Predicate.or methods have been extended so that any arrays or parameters passed into these methods are automatically filtered to exclude null or undefined ‘predicates’. This allow for simpler composition of complex query expressions.
// works even if any or all of pred1, pred2 or pred3 is null or undefined.
var predicate = Predicate.and([pred1, pred2, pred3]);
var query = breeze.EntityQuery.from("Employees").where(predicate);
EntityQuery with a “take(0)” method call is now supported and will return no entities. This idiom is useful in conjunction with the EntityQuery.inlineCount method.
// returns just the count of employees
var query = breeze.EntityQuery.from("Employees").take(0).inlineCount(true);
ES5 properties defined within an inheritance hierarchy via JavaScript’s Object.defineProperty method are now fully supported in any custom constructors registered with Breeze. This support is currently limited to AngularJS (via the backingStore adapter) and Knockout. Backbone support for this feature is coming soon.
Typescript breeze.d.ts file updated for TypeScript 0.9.1
Use them as you would the other stock validators. Here’s an example:
// Add Url validator to the blog property of a Person entity
// Assume em is a preexisting EntityManager.
var personType = em.metadataStore.getEntityType("Person"); //get the Person type
var websiteProperty = personType.getProperty("website"); //get the property definition to validate
websiteProperty.validators.push(Validator.url()); // push a new validator instance onto that property's validators
With the breeze.Validator.makeRegExpValidator
static helper, you can quickly mint new validators that encapsulate a regular expression. For example, we can create a U.S. zipcode validator and apply it to one of the Customer
properties.
// Make a zipcode validator
function zipValidator = breeze.Validator.makeRegExpValidator(
"zipVal",
/^\d{5}([\-]\d{4})?$/,
"The %displayName% '%value%' is not a valid U.S. zipcode");
// Register it with the breeze Validator class.
breeze.Validator.register(zipValidator);
// Add it to the Customer.PostalCode data property. Assume em is a preexisting EntityManager.
var custType = em.metadataStore.getEntityType("Customer"); //get the Customer type
var zipProperty = custType.getProperty("PostalCode"); //get the PostalCode property definition
zipProperty.validators.push(zipValidator); // get that property's validators and push on the zipValidator
See the API docs for more information on how to use these new validators.
Many of these new validators correlate to .NET data annotations. In a future release, the Breeze.NET
EFContextProvider
will be able to include these validations in the metadata automatically for you. For now, you’ll have to add them to the properties on the client side as shown above.
New server-side interception point, AfterSaveEntities.
New options for server-side transaction control. SaveChanges
now has an optional TransactionSettings parameter, which controls the type of transaction that wraps the BeforeSaveEntites
, SaveChangesCore
, and AfterSaveEntities
methods.
New methods on ContextProvider for use in BeforeSaveEntities
and AfterSaveEntities
. These methods help allow re-use of database connections, which reduces the need for distributed transactions.
Save validation enhancements. (Communicate server side validation errors to the client.)
Server side validation errors can be returned in using .NET Validation Attributes or by throwing an EntityErrorsException within the server side BeforeSaveEntities delegate or virtual method.
entityAspect.removeValidationErrors has changed
old signature: removeValidationErrors(validator, property)
new signature removeValidationErros(validationErrorOrKey)
If you don’t have a ValidationError you can obtain a key via ValidationError.getKey(validator, property); If you do have a ValidationError, it now has a publicly avail ‘key’ property that can be used to remove it manually if necessary.
The description of client side validation errors caught during a save before posting to the server has changed.
Client side validation errors caught during a save, but before posting to the server, cause the save to fail and be routed to the fail promise. The fail promise returns an error object that contains a description of the errors. This description has changed.
Previously this error object contained an entitiesWithErrors property that contained a list of all of the entities that had failed validation. This property has now been replaced with the entityErrors property. The entityErrors property returns a collection of entityError objects as described above.
This change was made in order to retain consistency between save failures that occurred on the server and those that failed before posting to the server on the client.
The ContextProvider base class has been changed - 3 new abstract methods were added and one method signature was changed. This change will ONLY affect developers who directly subclassed the ContextProvider base class. The EFContextProvider experienced no breaking changes.
Prior release notes are also available.