How to save a server generated complex object tree with entities that are not yet exsisting in the database?

StackOverflow https://stackoverflow.com/questions/14519919

Question

In my spa I need to send a complex object tree to the client and let the user fill in his data, before the entities can be saved in the database. So the entities do not exist in the database at that moment. The object tree is constructed in memory on the server and simply fetched by a call to breeze.EntityQuery.from("ComplexeObjectTree"). The entities a bound via knockout to a web form. The user than enters the required data first, before he can push the save button. Some of the entities properties in the form are optional and have default values. If the user doesn’t change these properties, beeze will not detect any changes and will not put its owning entities into the change set. They are marked unchanged but their id values are still -1 (not saved yet). But the database save can only be executed successfully, when all entities in the object tree including their relations have been send to the server (to respect database constrains). The save operation should result in one or multiple insert statements, also for those entities that have not changed on the client, but are new to the database (id==-1). How can I handle this use case? Shouldn’t all entities with primary key id==-1 marked as Added and be part of the save change set by default?

Any help is very much appreciated,

Andreas

Was it helpful?

Solution

Let's do it your way and accept your claim that the object graph must be constructed on the server. If I understand properly, you are offering the user an opportunity to tweak some of the values you generate on the server before committing them to permanent storage. Sounds like a fine plan.

"ComplexObjectTree" does NOT have to be an entity graph. It can be an arbitrary data object. It could still be a CLR type but it wouldn't be (or contain) objects described in metadata nor would they be known to EF or to the Db. This object graph exists simply as info that drives construction of the real entity graph on the client. It has all the hard-to-calculate values in it that you don't want calculated on the client ... like the answer to the meaning of life and who wins the Super Bowl this year.

Your query returns this object with data but no entities in it. The querySuccess callback, CreateComplexTree(data), will make the entity graph on the client out of this data.

The entity graph will be composed of entities understood by the Breeze client, thanks to metadata. Unless you have an objection, these entities are also understood on the server and are ready to save and query like any other entities (you can work around that assumption if false ... but let's work on one problem at a time).

So you're all set. You walk your data graph, creating the entities as you go. When you see (-1) in the data, you know to create a new instance of the type. Copy the data into the entity initializing object which is the second argument in manager.createEntity('Foo', {...}). There's no business logic here - no calculation - just the monkey-work of copying.

I can't tell if EVERY object within the graph is to be inserted or only some of them. Maybe some of them are pre-existing entities that are unchanged unless the user changes them too. No biggie. You can follow the same approach to construct "Unchanged" entities on the client with a line like manager.createEntity('Bar', {...}, breeze.EntityState.Unchanged).

Now you have a proper Breeze entity graph, ready for binding, navigating, and saving. If the user loves it just the way the server created it, she presses the [Save] button, Breeze finds all the changes in the entity graph, and off they go to the server.

As Bryant observes, you can't really trust the client. You'll want to walk the graph to validate it. But that's true regardless of your methodology.

Hope this helps.

OTHER TIPS

Typically you would create the entities on the client and not on the server. That way the entities are new and would be saved in the save method.

Since the entities are coming from the server and they aren't being changed on the client, there is no reason for the server to do anything with them when they come back since they are in the same state as when they left.

So create you new entities on the client and then call save changes.

Bryant is entirely correct is his answer. This answer is simply to get clarification.

Not entirely sure I understand the question but just to be clear the breeze EntityManager does not support multiple entities of the same type with the same 'key' (i.e. -1 in your case). It treats all entities of a single type with the same key as being the 'same' entity.

It sounds like what you want to do is retrieve a bunch of 'fake' entities into the entityManager and then conditionally convert a few of them into 'real' new entities' and save them causing these records to be added to the database. Is this what you are trying to accomplish?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top