Update or Delete BreezeJS EntityManager After Losing Instance Reference

In the process of developing a CRM application with a single-page application structure, I am integrating BreezeJS and AngularJS. The implementation involves utilizing dynamically-generated tabs to display various modules. Each time a user clicks on a menu item, a new tab is created, loading an HTML template (referred to as a module) into the content area. While some modules, like a grid of Accounts, are designed to be opened once at a time, others such as the Account Editor can be opened multiple times concurrently. This setup allows users to edit numerous accounts within a single instance of the Accounts grid.

To handle the Account Editor module effectively, I have established a system where a primary Breeze EntityManager is configured with essential parameters and then replicated when creating a new Account Editor using masterManager.createEmptyCopy(). The code for this process can be found at .

var serviceName = "/breeze/accounts";

var ds = new breeze.DataService({
    serviceName: serviceName,
    hasServerMetadata: true
});

var masterManager = new breeze.EntityManager({
               dataService: ds,
               saveOptions: new breeze.SaveOptions({ allowConcurrentSaves: false })
           });

function createManagerCopy() {
    var sandboxManager = masterManager.createEmptyCopy();
    return sandboxManager;
}

Subsequently, I execute an EntityQuery by passing the copied EntityManager and entity Id (key) to retrieve the necessary Account information and populate each open editor seamlessly using Breeze functionalities.

function queryAccountByKey(mgr, key) {
    var keyPredicate = breeze.Predicate.create('id', 'eq', key);
    var query = new breeze.EntityQuery('AccountsBase')
                          .expand('ContactsBase')
                          .where(keyPredicate);

    var promise = mgr.executeQuery(query)
                     .catch(queryFailed);

    return promise;

    function queryFailed(error) {
        console.log('Query Account by Id Failed', error);
        return $q.reject(error); 
    }
}

Although no conflicts arise among open editors and their respective entity managers as long as the copied EntityManager remains in the Angular scope of the module. Editing and saving become simplified and efficient.

However, a challenge arises when transitioning to another Angular route like a login screen and returning to the home screen. Due to the intricacies of each tabbed module, any previously opened Account Editor modules must be reloaded from stored settings to avoid having multiple Breeze entity managers handling the same account. This situation leads to changes being committed multiple times for a single Account Editor.

The main issue revolves around accessing a specific EntityManager instance upon revisiting the home layout when the original reference in the scope is lost. Is there a method to query or remove an instance from an EntityManager collection to streamline this process? Insights on how to manage instances efficiently or suggestions for alternative approaches would be highly appreciated.

SOLUTION

After implementing PW Kad's suggestion, I solved the dilemma by reusing entity managers instead of recreating them every time. By storing them in an object collection on the $rootScope when initialized and assigning a unique ID to associate with each tab, I could easily access and manage these instances throughout the Angular app without cluttering the global namespace.

The updated code snippet showcases this improvement:

// Addition of 'entityManagers' object to the $rootScope
angular.module('app', [])
.run(['$rootScope', function($rootScope) {
    $rootScope.entityManagers = {};
    $rootScope.entityManagers.count = 0;
}]);

// Within the dataServices factory:
var serviceName = "/breeze/accounts";

var ds = new breeze.DataService({
    serviceName: serviceName,
    hasServerMetadata: true
});

var masterManager = new breeze.EntityManager({
    dataService: ds,
    saveOptions: new breeze.SaveOptions({ allowConcurrentSaves: false })
});

function createManager(instanceId) {
    var sandboxManager = masterManager.createEmptyCopy();

    // Storing the EntityManager instance in $rootScope
    $rootScope.entityManagers['EM_' + instanceId] = sandboxManager;
    $rootScope.entityManagers.count++;

    return sandboxManager;
}

// To delete the EntityManager from $rootScope if needed
function deleteManager(instanceId) {
    var manager = $rootScope.entityManagers['EM_' + instanceId];
    manager.clear();
    delete $rootScope.entityManagers['EM_' + instanceId];
    $rootScope.entityManagers.count--;
}

// Integration within an Angular controller
$scope.instanceId = '1234'; 

$scope.init = function() {
    var manager = $rootScope.entityManagers['EM_' + $scope.instanceId];
    if (manager === undefined) {
       $scope.entityManager = 
              entityManagerService.createManager($scope.instanceId);
    } else {
       $scope.entityManager = manager;
    }
}

$scope.getEntityById = function(id){
    //utilize $scope.entityManager here to query database via Breeze
}

While questions about the internal storage location of BreezeJS’s EntityManager collection persist, this solution offers a practical workaround. Hopefully, this detailed explanation provides assistance to anyone encountering a similar scenario!

Answer №1

Reinstantiating a new entity manager every time you change pages may not be the best design choice as it can lead to losing the caching mechanism and prevent sharing entities across pages. However, if you must proceed with this approach, you can easily achieve it with the following code snippets:

var manager = {};

manager = manager ? manager.clear() : new breeze.EntityManager();

or

manager = manager ? (function () { delete manager; return new breeze.EntityManager(); })() : new breeze.EntityManager();

There are various other methods to accomplish this as well.

However, it is advised not to reinstantiate the entity manager each time. Instead, consider using logic like the following:

var manager = {};

// Some route activation logic
if (!manager) {
    manager = new breeze.EntityManager();
}

Edit

The reason why deleting the entity manager instance directly may not work could be due to how the breeze object in the global namespace references the entity manager. To manage multiple instances, you can create an object called `entityManagers` in either a closure or the global namespace, for example:

window.entityManagers = {};
window.entityManagers.count = 0;

To create a new manager instance:

window.entityManagers.createNewManager = function (name) {
    window.entityManagers[name] = new breeze.EntityManager();
}

window.entityManagers.createNewManager('ManagerNumber1');

And to dispose of a specific instance:

window.entityManagers.deleteManager = function (name) {
    window.entityManagers[name].clear();
    delete window.entityManagers[name];
}

window.entityManagers.deleteManager('ManagerNumber1');

This method should effectively remove the entityManager from use, assuming there are no other references to that specific instance. Consider the specifics of your use case before implementing this solution.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Could you explain the contrast among "yarn serve," "yarn start," and "yarn build"?

Although both "yarn serve" and "yarn start" can launch my Vue project, I'm unsure of the differences between them. I've heard that "yarn build" is for packaging, but why don't I use it at work? Usually, I just upload my code to git and let ...

What is the process for assigning an item from the result list to the parent Div tag of the current object?

I've been working on a function to insert the number of Facebook Likes into a Div tag. The script I have so far can extract the URL from a Div tag inside another Div named 'entry'. Then, using the .getJSON() method, it fetches the Facebook l ...

Issue with jqLite's .triggerHandler() functionality not behaving as anticipated

I'm having an issue with a piece of code that uses triggerHandler. The event is being called correctly, but it's not working as expected. Below is the code snippet and a link to a jsFiddle : HTML: <body ng-app="app"> <button box-cr ...

Interactive data table feature in React, transferring selected row data to a modal pop-up

I am currently developing an offline Progressive Web App (PWA) using ReactJS and have integrated the react-data-table-component, which has been very helpful so far. Within the table, I have implemented an onRowClicked function that triggers whenever a row ...

Retrieving CSS resources through AngularJS

As a beginner in AngularJS development, I am faced with the challenge of dynamically loading a CSS template for a page. This involves retrieving the name of the CSS template from a JSON object returned by an HTTP Servlet. It is crucial that Angular is ca ...

Looping through an array in Angular with ng-repeat

In my controller, I have managed to loop through the primary xml-based data successfully. However, I am facing challenges in passing the secondary child data (in the second level tr tag where I want all "list" categories to repeat) within the loop. angula ...

Error: Attempting to assign a value to the property 'running' of an undefined variable

While working with Nuxt.js, I encountered an issue related to reading the running property of my client object. Here is the HTML code snippet: <b-button v-show="!(projectSelecter(project.ID)).isStarted" //this work just fine variant="success" c ...

The error message that occurs when using angularjs $scope.$apply() is: Error: [$rootScope:inprog]

Having trouble updating text on a page within the $scope. Facing this error message: Error: [$rootScope:inprog] [http://errors.angularjs.org/1.2.15/$rootScope/inprog?p0=%24apply] at Error (native) at https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/ ...

What is the best way to organize Node/Express routes based on their type into different files?

My /router/index.js file is becoming too cluttered, and I want to organize my routes by group (user routes, post routes, gear routes) into separate files within /router/routes/. Here's what I currently have set up: app.js var express = require(&apos ...

Resetting the quiz by utilizing the reset button

Hello everyone, I'm new to this platform called Stack Overflow. I need some help with my quiz reset button. It doesn't seem to be working as intended. According to my code, when the reset button is clicked at the end of the quiz, it should bring ...

What is the best way to group Angular $http.get() requests for efficiency?

My challenge involves a controller that must retrieve two distinct REST resources to populate two dropdowns. I want to ensure that neither dropdown is populated until both $http.get() calls have completed, so that the options are displayed simultaneously r ...

Utilize a different variable for the display without altering the original model

Within my object, there resides a collection of items labeled X. Each X contains a list of Y items, and each Y contains a list of Z items. I am seeking a solution to hide the span upon clicking a button without altering the object itself. One approach inv ...

Organizing a Collection of Likes within an AngularJS Service

I have a like button on my profile page that, when clicked, should add the user's like to an array and store it in the database. Within my profile controller, I have the following code: $scope.likeProfile = UserService.likeProfile(loggedInUser,$stat ...

Converting Excel sheets to JSON using Vue.js

Struggling with reading excel files in vue.js as the memory usage spikes to 5GB after processing a small file. Need help converting the file to JSON format. Tried various options mentioned in the documentation but encountered different errors. Also checked ...

Manage the material-ui slider using play and pause buttons in a React JS application

I have a ReactJS project where I am utilizing the continuous slider component from material-ui. My goal is to be able to control the slider's movement by clicking on a play button to start it and stop button to halt it. Below is the code snippet of th ...

Creating an import map using jspm2 can be done by following these steps

Currently, my goal is to utilize JSPM module loader to import javascript packages from npm instead of CDN and employ an offline package loader. Now, the next step involves incorporating an importmap script in order to successfully import modules like rea ...

Looking to showcase website HTML code by simply clicking on a banner image?

I am looking to implement a feature where banner HTML code is displayed in a popup on website when the banner is clicked. For instance, an example of a banner could be: <img src="https://myweb.com/images/banners/1.gif"> Upon clicking the banner im ...

Steps to stop mat-spinner upon receiving Job Success/Failure Notification from the backend

I have a task that runs asynchronously and takes a long time to complete. When the task starts, I display a mat-spinner with a timeout set at 60000 milliseconds. However, we now have a notification service that provides updates on the job status. I would l ...

The audio stops when the ngaudio screen is clicked

When it comes to playing audio using the ngAudio service in AngularJS 1, the following code snippet is commonly used: $scope.audio = ngAudio.load("abc.wav"); $scope.audio.play(); However, some users have reported that after the sound is played, clicking ...

How can I resolve the "web page not found" error when using jQuery .replace()?

Working on HTML and javascript/jquery scripts, I have encountered a peculiar issue. My script utilizes a for-in loop to iterate through a JavaScript object, substituting specific patterns in HTML-formatted lines with data from the object using jQuery .appe ...