Question

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:

  1. This workaround is working and has been tested.
  2. This query usually works, but it doesn't work (returns wrong status id) just on this case when it is fired just after the status of the entity changes on the server, but the right status value comes on the response from the server (that's checked).
  3. So it is definitely a problem on the client parsing.
  4. The results ARE always populated and no errors are thrown (tested adding a fail handler). The issue is that the values are incorrect (and different from the ones on the json of the response).
  5. Guessing from what I see, it seems to be populating the results with an older version of the entity from the local storage (???), although that seems very odd, because there is no error and the results come back OK from the server. And also the populated data doesn't even match the data from the previous time it was executed sometimes.
  6. This happens using Breeze.js version 1.3.0, and although it looks like we could test migrating to the current version, 1.4.8, to see if that fixes the problem, I would like to know first if there isn't some other way to fix it and prevent issues like the one pointed out here: Breeze.js parsing XHR.responseText, to then asses if we should try any option or just keep the workaround.

Any ideas?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top