is there an easy way to mark an entity in the cache as "added"? - breeze

i would like to set an entity sent from the server to "added". it looks like entityaspect has methods setdeleted, setmodified, etc... but i can't seem to find one called setadded... what is the cleanest way to set an entity to "added"? i was thinking perhaps i would need to detach and then attach as "added". i have a server method called "newdeal" which creates a new entity ready for data entry... this method has business logic which i would prefer to keep on the server... when it gets to the client the entity is marked as "unmodified" which makes sense... but i would then like to change it to "added"...
thank you

#giancarloa, I'm assuming that, by the time the entity is sent from server to client, it has been persisted in the database. If that's the case, it wouldn't make sense to have its entityState set to Added as it would cause a duplicate error. If that's not how it works, please explain in detail what you are doing as I'm trying to get an idea of all the steps you're taking.
I'm also confused as to why create an entity in the server, send it to the client, update it, and then send it back to the server to save it in the DB - this just appear to cause more traffic and possibly reduce performance. Also, what it the user decides not to save? - then the work in the server would've been wasted.
Why not create the entity in the client and if it turns out to be saved, then the business logic would kick in the server during the beforeSaveEntity/beforeSaveEntities?

I had a similar problem. The breeze expect that entities returned from the server already exists in your database. This is not the case if your server fetched the entities from some other sources (not the database), returned them to client and then user can decide to the client if those entities should really be inserted in the database.
As you indicated, what you must do is skip the code that adds the entities into client's entity manager. later, you can add the detached entities to Entitymanager.
See the following answer for more details.
https://stackoverflow.com/a/18596070/174638

Related

Coredata safe clear subEntities

I want to ask for a safe way to clear subEntities in coredata.
I have my a many-to-many relationship like this: Product *<->* Product. Therefore, I've got to create a subEntity to hold some special values between (sortPosition, groupName.....).
So it's like this: Product *<->1 ProductSubEntity 1<->*Product.
When I download products from server's API, the easiest way to update correctly correspond to the server's result is:
Remove all child relationship ([self removeProductSubEntities:self.subEntities]).
Add sub from server's result.
Result: There'd be a lot of subEntity in coredata (which won't hold relationship to any product), and this might take storage/memory/cpu when CRUD (I think?). But I can't actual delete the subEntity (in case it's being hold reference to as an viewController's Object somewhere, and it might cause crash: access to a deleted object).
QUESTION:
How can I clear those sub entities (might occur sometimes) if:
No relationship to any product.
No actual reference from anywhere (any viewControllers or objects)???
P/S: I'm thinking of implement a batch delete when terminate app. Could that be consider a safe solution?
I don't consider this to be a datastore issue, rather a UI update issue. You should delete the objects from the datastore when you don't need them any more and you should update the UI accordingly.
1 thing you didn't mention is re-use. It's possible that your download may be an update to an existing item, which you could find and update, then life is easy all round. Arguably everything below still applies in this case though as your UI might not update to reflect changes and you may need to refresh the managed object.
For the UI update it's generally wise to observe the datastore for changes, usually with an NSFetchedResultsController. If you're doing this then your UI would automatically update itself with the changes.
If you're explicitly passing entity instances around then you should have some way to trigger an update explicitly, and exactly how that works depends on your UI. Generally speaking you'd be doing something like posting a UINotification to tell the system that the datastore changed and they need to re-validate their data objects. For the UI you shouldn't be showing now-dead objects to the user, and in your question where you talk about not deleting to avoid crashes, it's probably worse to allow the user to update invalid objects and just quietly not telling them that their updates won't be saved. When the notification is received you may want to pop a (some) controller(s) off the stack, or re-query the datastore for the new data to be displayed.
If for some reason you don't want to do the above, then yes, you can query for all of the entities with a nil relationship and then batch delete them. This should be done on a background thread just like data loading and I'd recommend doing it on app load instead of close (because you won't have so many view controllers loaded and the ones that are should all have only valid references now...).

Breeze.js: Returning empty set when requested database does not exist

Currently we are using Breeze.js and Angular to develop our applications. Due to some persistent legacy issues, we have two databases ('Kenya' and 'Rwanda') that cannot be merged at this time, but have the same schema and metadata. Most of the time, the client knows which database to hit and passes the request through the .withParameters() function or the .saveOptions() function. Sometimes we want to request the same query from both databases (for example, if we are requesting a list of all available countries), and we use a EntityManager wrapper on the client to manage this and request the same query from each database. This is implemented through a custom EFContextProvider which uses the data returned to determine the appropriate database and creates the appropriate context in CreateContext().
To further complicate things, in some instances one or the other database won't exist (these are local deployments created through filtered replication), but the client won't know this. Therefore, when querying for a list of all countries, it issues two requests and one will cause failures because the context cannot be instantiated properly.
This is easy enough to detect on the Server. What I would like to do is to detect whether the requested context is available and, if not, return a 200 response and an empty set.
I can detect this in the Breeze DBContextProvider CreateContext() method, but cannot figure out how to cause the request to fallback gracefully to a empty-set response.
Thanks
Not exactly what I was looking for, but it probably makes more sense since most of the work is being done on the client-side:
Instead of trying to change the controller, I added a getAvailableDatabases to the C# controller actions and use that to determine which of the databases I will query from the client.

Rails: working on temporary instance between requests and then commit changes to database

I have already read Rails - How do I temporarily store a rails model instance? and similar questions but I cannot find a successful answer.
Imagine I have the model Customer, which may contain a huge amount of information attached (simple attributes, data in other tables through has_many relation, etc...). I want the application's user to access all data in a single page with a single Save button on it. As the user makes changes in the data (i.e. he changes simple attributes, adds or deletes has_many items,...) I want the application to update the model, but without committing changes to the database. Only when the user clicks on Save, the model must be committed.
For achieving this I need the model to be kept by Rails between HTTP requests. Furthermore, two different users may be changing the model's data at the same time, so these temporary instances should be bound to the Rails session.
Is there any way to achieve this? Is it actually a good idea? And, if not, how can one design a web application in which changes in a model cannot be retained in the browser but in the server until the user wants to commit them?
EDIT
Based on user smallbutton.com's proposal, I wonder if serializing the model instance to a temporary file (whose path would be stored in the session hash), and then reloading it each time a new request arrives, would do the trick. Would it work in all cases? Is there any piece of information that would be lost during serialization/deserialization?
As HTTP requests are stateless you need some kind of storeage between requests. The session is the easiest way to store data between requests. As for you the session will not be enough because you need it to be accessed by multiple users.
I see two ways to achive your goal:
1) Get some fast external data storage like a key-value server (redis, or anything you prefer http://nosql-database.org/) where you put your objects via serializing/deserializing (eg. JSON).
This may be fast depending on your design choices and data model but this is the harder approach.
2) Just store your Objects in the DB as you would regularly do and get them versioned: (https://github.com/airblade/paper_trail). Then you can just store a timestamp when people hit the save-button and you can always go back to this state. This would be the easier approach i guess but may be a bit slower depending on the size of your data model changes ( but I think it'll do )
EDIT: If you need real-time collaboration between users you should probably have a look at something like Firebase
EDIT2: Anwer to your second question, whether you can put the data into a file:
Sure you can do that. But you would need some kind of locking to prevent data loss if more than one person is editing. You will need that aswell if you go for 1) but tools like redis already include locks to achive your goal (eg. redis-semaphore). Depending on your data you may need to build some logic for merging different changes of different users.
3) Another aproach that came to my mind would be doing all editing with Javascript and save it in one db-transaction. This would go well with synchronization tools like firebase (or your own synchronization via Rails streaming API)

delete entities which are not represented on the server side

I want to remove all entities which are not represented on the server anymore (e.g when another client deletes it).
My current approach is to delete all entities from a specific type which are not returned after a query anymore:
Get and cache all local entities from specific type
Make the query
Compare old entities with new entities which are returned from the query and detach it from entity manager
This seems a little work for me and i wonder if there not an easier way (maybe breeze already has something) to do that?
It's a good question. We refer to these types of entities as "ghosts". They are entities that are queried from a server by one user and later deleted by another user. The entities on the first client have now become 'ghosts'.
We have an existing feature request that would automatically 'detach' these if and only if a primary key requery occurs. The reason for this is that unless the entity was fetched by primary key we cannot determine that it is a ghost. We have not yet implemented this feature but are considering it for one of the near term releases. Would this feature be of use to you?

Breeze SaveChanges partial fail

I'm thinking at the following scenario: on the client-side you update two entities and you submit the POST with the json bundle. On the server side you do an interception and apply some business logic. The save works for one of the entities, however for the other one it fails. In your opinion what will be the correct solution and why: 1. should I do a rollback and return an exception on the client, or 2. commit the update for the 1st entity and return a message that the save worked only for one of the entities? I know that the guys from IdeaBlade consider the saveChanges as a single transaction(so all CRUD functionality goes in a single POST), so judging by this I think 1. should be correct approach. However I appreciate all reasoned opinions.Thanks!
Well it depends on what your doing. I bet you would save a lot of time developing if you just roll back. If you really want to though, you can return a list of failed and successful entities saved. Then the user (assuming the errors are user errors) can make the changes on the errored entities and commit only them again. This may become difficult though. Breeze attaches a state to each entity, which you will need now need to manage. So on the response, you'll need to figure out which entities failed and which succeeded, then update their state on the client, otherwise you'll resubmit commits that you don't need to. I think it would be a better investment on time to put this business logic on the client, then roll back on the server (and log the event so you can fix it) for the rare occasions errors occur. Does that help?

Resources