Search code examples
breezemultiple-repositories

How to import entities after save changes with breeze across two entity managers


I've implemented repository pattern with two entity managers, mainManager is for read only and delete, and updateManager is used for edit and add new entities. I use createEmptyCopy() to create updateManager.

Before i update an entity i export the entity from mainManager and import into the updateManager, after the change i call to updateManager.saveChanges() method.

I've noticed that i get back the updated entities in the promise response. i wonder what is the best practice to import those entities back into the mainManager?

here is my code:

function ($q, $http, entityManagerFactory) {
    var self = this;

    self.mainManager = entityManagerFactory.newManager();
    self.updateManager = entityManagerFactory.newManager();

    self.saveChanges = function () {
        return self.updateManager.saveChanges();
    };

    self.rejectChanges = function() {
        self.updateManager.rejectChanges();
    };

    self.getDomains = function () {
        self.mainManager.clear();

        var query = new breeze.EntityQuery()
            .from('Domains')
            .orderBy('name');

        return self.mainManager.executeQuery(query);
    };

    self.createEmptyDomain = function () {
        var domain = self.updateManager.createEntity('Domain');

        return domain;
    };

    self.editDomain = function(domain) {
        var exported = self.mainManager.exportEntities([domain]);
        return self.updateManager.importEntities(exported).entities[0];
    }

    self.addDomain = function (domain) {
        self.updateManager.addEntity(domain);
        return self.updateManager.saveChanges();
    };

    self.deleteDomain = function (domain) {
        domain.entityAspect.setDeleted();
        var deferred = $q.defer();
        self.mainManager.saveChanges().then(
            function(data) {
                deferred.resolve(data);
            },
            function (reason) {
                console.log(reason);
                self.mainManager.rejectChanges();
                deferred.reject(reason);
            });

        return deferred.promise;
    };
}

Right now i'm calling mainManager.clear() and get the data again from the server as you can see above in getDomains function. But i think this is too expansive, why call the server if i already have the updated entities from the saveChanges promise?

i've also tried to import those entities back to mainManager using:

mainManager.importEntities(data.entities, { mergeStrategy: breeze.MergeStrategy.OverwriteChanges });

but i get an internal null breeze exception:

TypeError: Cannot read property 'forEach' of undefined
    at EntityManager.proto.importEntities (breeze.debug.js:13081)
    at self.importEntities (domain-list.service.js:22)
    at domain-list.controller.js:70
    at processQueue (angular.js:13170)
    at angular.js:13186
    at Scope.promises.$get.Scope.$eval (angular.js:14383)
    at Scope.promises.$get.Scope.$digest (angular.js:14199)
    at Scope.promises.$get.Scope.$apply (angular.js:14488)
    at done (angular.js:9646)
    at completeRequest (angular.js:9836)

the error is from this line breeze.debug.js:13081

13080: var tempKeyMap = {}; 
13081:     json.tempKeys.forEach(function (k) { 
13082:       var oldKey = EntityKey.fromJSON(k, that.metadataStore); 
13083:       // try to use oldKey if not already used in this keyGenerator. 13084:       tempKeyMap[oldKey.toString()] = new EntityKey(oldKey.entityType, 
13085: that.keyGenerator.generateTempKeyValue(oldKey.entityType, oldKey.values[0])); 
13086:     });

Solution

  • var exportData = updateManager.exportEntities(data.entities, false);
                     mainManager.importEntities(exportData,
                        { mergeStrategy: breeze.MergeStrategy.OverwriteChanges });