We have an EntityQuery in Breeze.js that brings data consisting in one instance of an entity with data from related entities.
The data arrives correctly to the client. I can see the response from the server and also in the XHR.responseText that the data arriving from the server is correct.
But for some reason, sometimes the data does not populate correctly the results (that is built with the observables), the observables are there, but their values are incorrect. I'm explicitly pointing out that this is only sometimes. Because the same query with no changes, pointing to the exactly the same entity instance on the server, sometimes DOES populate the results correctly.
Since on those cases where the data wasn't parsed or populated correctly I see the correct data on the responseText I implemented an easy workaround/hack to resolve the problem, but I would like to know if there is some other better fix for this.
This is the query (entity name changed to Op for confidentiality reasons) and the workaround:
new breeze.EntityQuery('OpsWithRelatedData')
.where('Id', '==', id)
.using(self.EntityManager)
.execute()
.done(function (r) {
var op = r.results.pop();
// This is an ugly hack to prevent a Breeze problem
// (when it doesn't evaluate to an op correctly)
var evalOp = eval(r.XHR.responseText)[0];
if (evalOp.StatusId != op.StatusId()) {
viewModel.Op().StatusId(evalOp.StatusId);
viewModel.Op().Status().Id(evalOp.Status.Id);
viewModel.Op().Status().Name(evalOp.Status.Name);
} else {
viewModel.Op().StatusId(op.StatusId());
}
def.resolve(op);
});
Some additional info:
Any ideas?
I don't know for sure but the most probable cause of the behavior you describe is that the entity in question is in a changed state when the query data arrive.
You can test for this by checking the
EntityState
of each result entity in your query's success callback and raising the appropriate diagnostic alarm when the entity is in a changed state. I'll bet you confirm my hypothesis.
Breeze query results are merged into cache based on a MergeStrategy
. By default, that strategy is "PreserveChanges" which tells Breeze to ignore incoming values when the target entity has pending changes (that is when its EntityState
is anything other than "Unchanged").
I'm guessing that your queried entities are updated "most of the time" because they are in the "Unchanged" state most of the time. But occasionally something - a user, your app - puts the entity in a changed state and, while that in that state, new values arriving from the server are simply ignored.
This is expected behavior ... it is what "PreserveChanges" means ... and there is no reason for Breeze to throw an exception.
You could change to the MergeStrategy.OverwriteChanges
, either as the query default or on a per-query basis, if that is more appropriate for your use case.
On a personal note, I urge you to make no use whatsoever of the XHR
object. I don't understand why Breeze exposes it in the first place and some Breeze AJAX adapter implementations would be unable to deliver that object. If I have my way, it will disappear from the interface in future Breeze versions. Please treat its presence in the API as unintentional and unsupported.