Automatic refresh of data in a filterModule? - jspresso

The case that I have to deal with is :
An entity CustomerOrder with a list of TransportOrder.
A filterModule for each entity to be able to browse CustomerOrders and separatly to browse all TransportOrders of all CustomerOrders.
Depending on an action set on CustomerOrder, I generate multiple TransportOrders and update the CustomerOrder's status from "Forecasted" to "Validated".
Through the TransportOrder filterModule, the new TransportOrders are displayed.
A second action on CustomerOrder allows to get back the CustomerOrder to its initial status (ie "Forecasted") and consequently remove and delete the relevant TransportOrders.
The issue :
When a CustomerOrder is restored to its initial status, its former TransportOrders (that have been deleted) are always present in the TransportOrder filterModule (the filterModule's data are not automatically refreshed)
Is there a way to automatically refresh the data displayed in the TranportOrder filterModule ?

There is no automatic "cleaning" of module objects after a committed deletion of entities.
However you could easily chain an action after the one that reverts your CustomerOrder status in order to iterate through all your modules and remove the deleted entities if any from the modules moduleObjects collection (or do whatever you want with the module).
Implementing an automatic cleaning would not be that hard, but it would require hooking into the backend controller in order to be notified of any committed transaction, iterate through deleted entities and perform what I've described before. Of course, feel free to issue an enhancement request in GitHub for it.

Related

Multiple Dbset/entity modification with single call to SaveChanges()

I am working on a .NET Core Web API which needs to interact using EF Core 5.0.2 with an Azure SQL database.
I have different repository methods where I am interacting with DbContext to add/edit/delete records for different DbSet.
For example:
UserRepository.AddUser(userdata);
Implementation of AddUser is like this,
ourDbContext.UserTable.AddAsync(userdata);
So in user service method, am calling different repository method sequentially and none of those methods call ourDbContext.SaveChangesAsync() individually. A single call to SaveChanges is present after all the repository methods calls which is acting like a unit of work pattern for all the calls as single transaction.
Example:
UserRepository.AddUser(userdata);
ActivityRepository.AddActivity("New User got added");
ourDbContext.SaveChangesAsync();
So my question is: if any saving changes to any of the tables/entities fails, will the previous successful tables change will be rolled back?
For example, suppose this operation
UserRepository.AddUser(userdata);
was successful and the new user record was added to the User table.
But this was not successful:
ActivityRepository.AddActivity("New User got added");
So no activity record was added to the Activity table.
Will SaveChangesAsync() be able to handle this situation automatically and will roll back User table new changes as well?
If not are we supposed to wrap the above codes with transaction scope? Or what is the recommended way to do it.
Briefly how DbContext's Change Tracker works:
You load entities: ChangeTracker remembers current values of all loaded entities (except you use AsNoTracking())
You have modified loaded entities, delete, add new.
You call SaveChanges: ChangeTracker starts searching which objects are changed since last load by comparing with previous values.
DML SQL is generated and everything saved in one SQL statement or in several statements in Transaction.
So, if you have one DbContext for each repository, you do not need to worry about rollbacking, just do not call SaveChanges(). For sure for restart process, you have to recreate DbContext because it contains not needed state.

Approach for Vuex to update state - after - CRUD operations

Let's suppose I have a collection of books retrieved by a Vuex action called fetchBooks (this action commit the SETBOOKS mutation to change state).
When I dispatch the action remove to remove a book, I have two options:
1) Send request to the API to delete the resource and then dispatch fetchBooks to reload the books listing.
2) Send request to the API to delete the resource and then commit the REMOVE mutation to remove the book from state, without any additional HTTP request.
The first seems more easy, I can use the same technique for add/update/delete, with the price of doing an additional request to reload the listing.
The second is more cheap (no additional request), but require more logic to handle state for each add/update/delete case.
What is the right way to do it?
I would go with option 2.
In the general practice "getBooks" could be a huge array, and it is better not to requery the data from the DB when you already have it locally.
Just make sure you are deleting the book inside a try catch block, so if the delete doesn't go in the backend, you should alert the user.

Sencha Touch 2 - "quietly" delete and update records in localstorage

I have a sencha touch 2 web app that is using a localstorage datasource to store a bunch of records.
I am able to perform all the usual crud operations fine, but I want to sync data using a webservice. so periodically, the sencha app will poll the webservice for data changes and then make the necessary changes to the localstorage datasource of my sencha app..
My approach has been to use the following code block to run my sync process every 60 seconds:
var timerID = setInterval(function()
{
MyApp.app.BackgroundProcessingMain();
}, (60000));
Inside "BackgroundProcessingMain()", I have various method calls to sync the various datastores (5)..
I call the webservice and get the data I require back, and then my approach has been to loop through the returned data, filter my store to the id of the current item of the returned data and then either delete it, or update it as necessary.
This works fine.. BUT, if this background process kicks off and I'm viewing a bound list control, my list which is using a filtered version of my datasource, suddenly drops down to only showing a single item, usually the last one in the returned data that needs to be synchronised since it was the last one that my update process filtered the store to operate on.
I thought I could use store.findById, get the record reference and update/delete that way, but if the particular ID is already being filtered out due to the view my bound list requires, the record isn't found in the store and therefore doesn't get updated..
What I'd like to be able to do is get a temporary copy of the store, unfiltered, be able to modify it, and then when my app then queries the localstorage next time a form is shown, it will just get the new updated data..
That is basically what I'm referring to as "quietly" in the title..
Does anyone have a suggestion as to what process I could take to get this update done..??
If you have example code, that would be awesome, but pseudo-code is fine..
Thanks
You can use suspendEvents() and resumeEvents() to temporarily prevent your store from firing events. You can then clear your filters, apply your updates (using store.findById()), and reapply your filters without your list changing.
var store = Ext.getStore('myStore');
store.suspendEvents();
store.clearFilter();
doThings(...);
store.filter(myFilters);
store.resumeEvents();
If you pass true into store.resumeEvents(), the buffered events will be discarded.

Can I associate a change set with a work item after it has been delivered?

If I deliver a change set to a stream and not associate it with a work item can the change set be associated with a work item after it has been delivered ?
Yes.
The changeset itself is closed upon delivery to the stream.
But its associated work-item(s) is not: you can add or remove one or several work-items in association with the delivered changeset.
That being said, I have a special hook which makes that association mandatory on deliver: ie, you cannot deliver without having first associated your change set first to a Work Item.
I am not sure if that hook is a custom one for my organization, but here is where you can check if it is there:
It is in the Project Area administration, under
Team Configuration /
Operation Behavior /
Source Control /
Deliver (client) /
Preconditions and follow-up actions are configured for this operation /
Require Work Items and comments

How does one gracefully merge object graphs after NHibernate StaleObjectStateException?

We are trying to combine objects after a StaleObjectStateException has been thrown to save a merged copy.
Here's our environmental situation:
List item
Multi-user system
WPF Desktop application, SQL Server 2008 database
NHibernate 3.1.0.4000, FluentNHibernate 1.2.0.712
Global, long-running NHibernate sessions [for the moment. We understand session-per-presenter is the recommended pattern, but do not have time in our project schedule to convert at present.]
Top-down saves and property navigation (that is to say we save the top-level object (herein called Parent) in our domain graph)
.Cascade.AllDeleteOrphan() used in most cases.
Users exclusively own some objects in the domain graph, but share ownership of the Parent.
Navigation properties on Children objects do not exist.
All classes have numeric ID and numeric Version fields.
Use case:
User 1 starts application and opens Parent.
User 2 starts application and opens Parent.
User 2 adds a child (herein C2).
User 2 saves Parent.
User 1 adds a child (herein C1).
User 1 saves Parent.
User 1 receives a StaleObjectStateException (and rightly so)
We want to gracefully handle the exception.
Because the users share ownership of the parent, User 1 should be able to save successfully, and save the Parent with both his new child, and User 2's child.
When SOSE is thrown, according to Ayende (http://msdn.microsoft.com/en-us/magazine/ee819139.aspx):
your session and its loaded entities are toast, because with NHibernate, an exception thrown
from a session moves that session into an undefined state. You can no longer use that session
or any loaded entities
C1 has already been assigned an ID and Version # by the now-not-useful session. (I wish it had not been.)
How do we combine the use of ISession.Merge() and ISession.Refresh() to get a newly saved Parent that has both C1 and C2 ?
We have tried a number of arcane permutations, none of which fully work.
Usually, either a "row was updated or deleted by another transaction (or unsaved-value mapping was incorrect" or an actual ID collision at the ODBC level.
Our theory, at the moment:
Reset version numbers on C1 (to prevent "unsaved-value mapping was incorrect")
Get a new session
newSession.Refresh(C1);
newParent = newSession.QueryOver[...]
newParent.Add(C1);
newSession.SaveOrUpdate(newParent)
However, all the documentation suggests that newSession.Merge is supposed to be sufficient.
Other posts used as research:
Fluent NHibernate Newbie: Row was updated or deleted by another transaction
Is there an alternative to ISession.Merge() that doesn't throw when using optimistic locking?
StaleObjectstateException row was updated or deleted by
How I can tell NHibernate to save only changed properties
Hibernate (JPA): how to handle StaleObjectStateException when several object has been modified and commited (java, but relevant, i think)
Because the users share ownership of the parent, User 1 should be able to save successfully, and save the Parent with both his new child, and User 2's child.
Why don't you just disable optimistic locking on the child collection? Then anyone can add childs and it won't increase the version of the parent.
Otherwise, here is the solution my current project uses for all recoverable exceptions a session could throw (e.g. connection to DB lost, foreign key violated, ...):
Before calling session.Flush() the session is serialized to a MemoryStream.
If session.Flush() or transaction.Commit() throws an exception that is recoverable, the original session is disposed and the saved one is deserialized.
The calling screen then gets the information that the session was recovered after an exception and calls the same queries again that were called when the screen was opened the first time. And because all the modified entities are still in the recovered session the user now has the state of just before he pressed save.