0

I'm using Wards excellent example of implementing many-to-many with breeze. (i'm going off the plunk in his post, cant link to it from here dont know why)

Everything is working great, changes are always saved to database correctly.

I am using 2 different (BreezeJS) EntityManagers: one for edits, and one as my "master". On saving the editor Em to database, it then imports all changes into the master Em so it all stays in sync. This has been working wonderfully for all my other functions.

However, when saving the many-to-many mapping, for some reason any deleted mappings are not removed from the master Em. (When I add mappings they correctly show up in the master Em right away).

Do I need to take another step to get my master Em to remove imported detached entities?

(FYI, everything is saving correctly to server, if I do hard page refresh, all my entities show up correctly).

My code for deleting entity on editor Em:myEntity.entityAspect.setDeleted();

Function below will export changed entities from editor Em:

  function exportToMasterAfterSavingSuccess(saveResult){
  if(saveResult.entities)
    masterEm.importEntities(manager.exportEntities(entities, false));
}

And the corresponding import function on master em:

function importEntities(entities){
 var imported = manager.importEntities(entities,{ mergeStrategy: breeze.MergeStrategy.OverwriteChanges});
}
Community
  • 1
  • 1
Rastographics
  • 389
  • 3
  • 12

3 Answers3

0

Please try this with the latest released version of breeze (1.5.3). A very similar bug was fixed there.

And just to be clear, and export can never include 'detached' entities ( only 'deleted' ones). Detached entities are, by definition, no longer attached to an EntityManager so the EntityManager no longer knows anything about them.

Jay Traband
  • 17,053
  • 1
  • 23
  • 44
  • oh sweet a brand new release! i'll check it out and get back – Rastographics Jan 22 '15 at 23:20
  • unfortunately the 1.5.3 release did not fix the problem. I don't know if this helps, but I noticed that the entities that *should* be removed from the master Em are always moved to the end of the list of entities. – Rastographics Jan 22 '15 at 23:33
0

I'm having the exact same issue. I'm not doing many-to-many but still doing edits/adds/deletes in a separate entityManager.

I can confirm that the export DOES include Detached entities, and on import into the master entityManager with MergeStrategy.OverwriteChanges, those entities do become detached.

However, the newly detached entities are still associated with any related entities.

Reattaching and detaching seems to get everything back in sync as far as I can tell:

var result = manager.importEntities(imports);
result.entities
    .filter(function (entity) { return entity.entityAspect.entityState.isDetached(); })
    .forEach(function (entity) { manager.attachEntity(entity); manager.detachEntity(entity); });

Breeze 1.5.3

Github issue with pull request: https://github.com/Breeze/breeze.js/issues/75

0

Thanks for uncovering a bug. One shouldn't be able to export or import a detached entity. In future, Breeze will throw if you attempt to do either.

Now I'll discuss your issue, your aims, and what I recommend that you do.

Update master EntityManager after saving deleted entities

As I understand it you maintain a masterEm which has only the saved state of entities. You make and save your changes in a separate editEm. You import entities that you will change into the editEm, make changes, save them, and (if the save is successful), you export the saved entities from editEm and import them back into masterEm. This is a common "sandbox editing" pattern.

Trouble arises when you delete an entity in editEm. After save, that entity is "Detached" in the editEm but it's still in an "Unchanged" state back in the masterEm. How do you communicate the fact that the entity is deleted and remove it from masterEm?

This dilemma exists independent of the "many-to-many" scenario that inspired your question.

I can see why your practice of importing the now-Detached entity from editEm to masterEm seemed to work. Doing that in v.1.5.3 caused the corresponding entity in masterEm to change to the "Detached" state ... which is what you wanted. The bug, as you saw it, was that the importEntities method didn't handle update of navigation properties properly when the imported entity is in a "Detached" state. You proposed teaching importEntities to "do the right thing" in that scenario.

What actually happened here is that you discovered a bug. You should never have been able to export a "Detached" entity and you shouldn't have been able to import one either. Breeze should have thrown an exception when you tried to export or import a "Detached" entity.

There are all kinds of reasons why asking an EntityManager to export/import "Detached" entities is a bad idea. I leave explication of those reasons for another day.

Rather than "solve" the problem of importing related "Detached" entities, we will throw an error.

This means that your partial solution will cease to work, leaving you apparently worse of than you are today. Fortunately, I have an alternative approach for you. I've written this utility function and tested it in DocCode:

function updateMasterWithSaveResult(masterEm, sourceEm, saveResult) {
  var imports = [];
  var deletes = [];
  saveResult.entities.forEach(function(entity) {
    if (entity.entityAspect.entityState.isDetached()) {
      deletes.push(entity);
    } else {
      imports.push(entity);
    }
  });
  var exported = sourceEm.exportEntities(imports, {
    includeMetadata: false,
    asString: false // as JSON
  });
  masterEm.importEntities(exported);

  deletes.forEach(function(detached) {
    var entity = masterEm.getEntityByKey(detached.entityAspect.getKey());
    entity && entity.entityAspect.setDetached();
  });
}

Updated documentation

I just added this to our "Cool Breeze" documentation almost verbatim.

Community
  • 1
  • 1
Ward
  • 17,793
  • 4
  • 37
  • 53
  • thanks Ward, just what was needed. I don't suppose there's a good place where this function would ever fit in the core. – Rastographics Feb 20 '15 at 18:44
  • It's possible. We haven't run into it before (to my knowledge) so I think we'll let it "cook". If the demand arises, we can bring it in. – Ward Feb 23 '15 at 22:29