BreezeJS and multipart keys

During one of our projects we decided to use a javascript library called Breeze.

Breeze is a very useful library that allows users to work with entities in js and to execute CRUD operations directly from js, almost without writing server code.

One of the problems we have encountered, however, was that it was quite difficult to add business logic on the server side before saving entities to the database. We have found 2 ways to approach this issue: One way is to work with JObject that is received by the save function. The second option is less obvious and is described in the Breeze documentation, which instructs the user to create custom database context provider nested from EFContextProvider and to override the BeforeSaveEntity function.

The fact that Breeze needs database metadata to work with entities was the second problem we faced because we used to work with only a few entities on a page. Breeze, however, sent information about all of the 40+ tables. This issue can be partially solved by creating a new context for Breeze with only a limited number of columns but it in our case, there was still a lot of extra table info because of relations.

The biggest problem we encountered, however, occurred when we started working with entities that have multipart keys. In our case we had a PK that consisted of 2 columns:

  • ProductId
  • TenantId

First of all, Breeze was unable to generate a new PK when the new item was added to the EntityManager. So we defined a custom entity initializer with a standard MetadataStore class function called registerEntityTypeCtor.

var manager = new breeze.EntityManager(“breeze service url”);
var store = manager.metadataStore;
 
function itemInitializer(item) {
   if (item.ProductId() == 0) {
  	item.ProductId(/*Some counter value*/);
   }
   if (item.TenantId() == 0) {
  	item.TenantId(/*Some tenant value*/);
   }
 
   if (item.isBeingEdited === undefined) {
  	item.isBeingEdited = ko.observable(false);
   }
};
 
store.registerEntityTypeCtor("Entity type name", function() {/*Leave empty to use default constructor*/}, itemInitializer);

In addition, we had problems updating that new entities with a new ids. Breeze was unable to update the ProductId with the actual id from EntityFramework.

We found out that this happened because Breeze stores entities’ indexes in a map with PK as a key that consists of 2 values, but save callback received only 1 value (identity). So in order to let Breeze find the proper entity we had to override the callback function, but for that to be possible, we needed to use a function that is not described in official API.

var entityType = store.getEntityType("Entity type name");
var entityGroup = manager.findEntityGroup(entityType);
 
entityGroup._fixupKey = function (tempValue, realValue) {
   tempValue += ":::" + TenantId;
   var ix = this._indexMap[tempValue];
 
   if (ix === undefined) {
  	throw new Error("Internal Error in key fixup - unable to locate entity");
   }
   var entity = this._entities[ix];
   var keyPropName = entity.entityType.keyProperties[0].name;
   entity.setProperty(keyPropName, realValue);
   delete entity.entityAspect.hasTempKey;
   delete this._indexMap[tempValue];
   this._indexMap[realValue + ":::" + TenantId] = ix;
};

The _fixupKey function is an internal function of the EntityGroup class (you won’t find it in the official API too) that handles key updating. To get the EntityGroup instance, you need to call another non-documented function of the EntityManager class, called findEntityGroup.

We have been working with Breeze 1.2.1 but up until 1.4.1, this problem has yet to be solved (the only difference is findEntityGroup is now called _findEntityGroup).

Summary

Breeze has its own benefits including:

  • less server requests
  • its own entities cache
  • no need to write a lot of server code

But one should think twice before using it because:

  • it is hard to implement business logic on the server side
  • it is unable to work with multipart keys out of the box
  • anyone will be able to see your database structure

Despite all of its disadvantages, Breeze is a great library that can facilitate the work of the developer, and we expect that this library will become more and more powerful with future releases. However, you should first carefully contemplate whether it would be useful for your project before proceeding. Hopefully this article will be of assistance in making this decision.

Comments

Thanks. It really help me. I

Thanks. It really help me.