Search code examples
asp.net-web-apibreezesavechanges

Breeze entity state doesn't change after saving


My application uses BreezeJS, ASP.NET Web API and EF.

I'm trying to save an object using breeze, as follows:

 var saveOptions = this.manager.saveOptions.using({ resourceName: "SaveLocationSettings", tag: clientId, allowConcurrentSaves: true });
 var obj = self.manager.saveChanges(null, saveOptions).then(saveSucceeded, saveFailed);

I'm using a custom save method on the server side, which returns a SaveResult object. However, on the client side, the entity manager still maintains the modified state.

My controller on the Web API is a BreezeController.

According to the breeze documentation, if your custom method has the signature similar to the Breeze SaveChanges() method, it should work similar to SaveChanges() method. However, if I use the breeze SaveChanges(), the entity state gets updated properly. But my custom endpoint save does not update the entity state, although the data is saved in the database.

UPDATE:

After some investigation, I figured that this happens only with one entity type that goes to this particular save endpoint. Say, I have a 'location' object, with a collection of 'availability' associated with it, as follows:

Class Location {
   public Location() {
         this.Availabilities = new HashSet<Availability>();
   }
}

Now from the client side, if I only change some property of the Location object, it handles the hasChanges property correctly. But if I change the Availability only or Availability along with another property of the location, then the hasChanges is not updated properly on client side.

This is my server side code that's called from the WebAPI controller:

     public SaveResult SaveLocation(Location l, List<MaxAvailability> maxAvailability, int changedBy)
    {
        // Create a SaveResult object 
        // we need to return a SaveResult object for breeze
        var keyMappings = new List<KeyMapping>();
        var entities = new List<object> {l, maxAvailability};

        var saveResult = new SaveResult() { Entities = entities, KeyMappings = keyMappings, Errors = null };

        try
        {
            if (l.LocationId == -1)
            {
                // add new location
                l.LocationId = this.AddNewLocationWithItsAssociatedData(l, maxAvailability, changedBy);
            }
            else
            {
                // do changes to the existing location
                this.UpdateExistingLocationWithItsAssociatedData(l, maxAvailability, changedBy);
            }
        }
        catch (DbEntityValidationException ex)
        {
            // Log the error and add the errors list to SaveResult.
            // Retrieve the error messages as a list of strings.
            saveResult.Errors = this.GetErrors(ex);
        }

        return saveResult;
    }

Solution

  • I think I figured out the answer. It was due to some bad practice in my code. When modifying the availability of an existing location, instead of updating the existing record, I was deleting the existing record and adding a new one. This was causing the client side availability object and the database object to have two different states. Once it was resolved, the hasChanges() state was behaving as expected.