SubmitChanges w/o UI disable

Dec 5, 2011 at 7:03 PM

I have a dashboard type interface with windows that have views that have column settings. I need to auto save the UI settings while allowing the UI to remain active. Each client / user / login has its own settings so there are no concurrency issues on the server.

The problem is that entities are set to read-only when SubmitChanges is pending. So, if a user drags a window, resizes a column etc. an exception occurs because the entity / property is locked as read-only during the submit process.

I have been looking at the partial change capabilities of EntityGraph and I see that recent features seem to provide most of what I need. However, the learning curve is pretty steep and I do not want to write code duplicating functionality the classes already contain. I am hoping for some guidance.

In my case, I do not necessarily need a partial change. A full submit is fine because my context only contains the entities I want to submit add/changes/deletes for.

I would like to implement a client wins strategy like so:

1. Save all changes to the server without requiring concurrency check against the original. It would be nice if I can get the server to optimize the changes by simple UPDATE without any re-fetch/checks (last wins).
2. On return to the client:
A. No Errors =
   i. Update calculated fields (Identity column is the primary key on all tables).
 ii. Keep any deletes/ changes / states that occurred on the client during the submit operation. These will be submitted during the next auto-save.
B. Error =
   i. Original context should have all old adds/changes/deletes and any new ones that occurred during the submit operation. The next auto-save will re-submit.

I think that clearing the original context’s states before submit will allow the concurrent changes to be tracked. Perhaps there is a better way?

I have read about the Partial Change methods, Synchronize, AcceptChanges etc. But, I am not sure about the path I should take.

First of all, I need to get the deletes submitted. Is there a simple way to move them to the temp context?

Secondly, the Synchronize looks like it will overwrite any changes that happened while the submit operation was in progress. Should I make a copy of the orig, apply the returned temp context changes and then apply the changes from the copy (so the concurrent changes take precedence)???

Hopefully, the code I need is simpler than I think?

Any and all suggestions will be appreciated.

TIA

Developer
Dec 22, 2011 at 8:20 AM

Hi,

What you want is currently not supported by EntityGraph. I'm working on a way to merge the changes of the temp context in the original, in order not to overwrite new changes in the original context. Deletions are also not very well supported.

Kind regards,

Merijn

Dec 22, 2011 at 2:57 PM

It is easier for me to clear the original's state before submit. That way changes that occur during the submit are tracked independently. I do not know what approach can be used within the EntityGraph library.

I do not know how to find the deletions for a graph. I do not see any code that tracks Removes.
For now, I am submitting all removed entities. It would be nice to be able to find only the entities that were part of a particular graph before being removed. I do not see any public methods available to match a removed entity to its original graph.

Not an EntityGraph issue - a DomainContext issue = on my system, calling Remove on a child collection leaves the Entity in the collection with a Modified state instead of adding it to RemovedEntities. However, Remove from EntityContainer.GetEntitySet removes it from the graph/parent and places it in the context's RemovedEntities? For now, I am only deleting entities from the GetEntotySet so they will be in the context's RemovedEntities.

Is there a way to remove an entity and have it listed in it's EntityGraph RemovedEntities??? It seems like RemovedEntities will never have items?

-------------------------------
Example logic flow:

Submit
  For each graph that HasChanges, 
    Clone to the temp context,
    add the graph and clone to a list (for use in OnDone), 
    graph.AcceptChanges (Entity properties need to have Update Check = Never and all identities unique)
  For each Removed entity - add to removed list, Attach to temp context, then Remove from temp context, entity.AcceptChanges
  tempContext.SubmitChanges(OnDone)

OnDone
  Only if Error -> for each in removed list - attach to context, then Remove 
  Always
    original.ExtractChangedSet
    graph[i].Synchronize(clone[i])
    original.ApplyChangedState

I had to pull in some contrib RIAExtensions code for the Extract/Apply

It seems to work -
Concerns:
  It would be nice if deletes (removes) were handled on a EntityGraph basis somehow. 
  Correct operation when Submit returns an error.  I believe Synchronize will put the mods back and the code is correct, but I am not sure what can happen with all of the possible errors.

What do you think?

Dean

Developer
Jan 7, 2012 at 8:52 PM

Hi,

I just added an overload of the Synchronize method that accepts a LoadBehavior parameter. With this parameter you can specify how the entities in two entity graphs are synchronized. In your case you would probably want to use LoadBehavior.MergeIntoCurrent. This will merge property values from a source entity into a corresponding target entity, while leaving modified properties of the target entity in tact.

Jan 11, 2012 at 8:45 PM
That will be handy as long as entities are not added or removed during the submit. Synchronize requires the graphs to be equal.
So, I wrote new sync code to work with a list of original entities instead of the original EntityGraph.
For me, being able to submit while allowing the UI to continue with concurrent adds, changes and deletes was absolutley necessary. 
The removed items are still not EntityGraph based, but I never cancel deletes so it does not matter if all deletes 
for the context are submitted.
The logic flow has changed - instead of adding the original graphs to a list, I add the entities (reference) in the 
original graph to a list (of lists = original). It would be nice to have a EntityGraph for these referenced entities
that would not change with adds or deletes, but I do not see a way to do that.
On SubmitChanges complete, I loop through the submitted clone entitygraph's entities which have a one to one correspondence to the original
entities list I saved. I then extract and apply states for each individual entity - just like the Synchronize Merge you provided does.
If you would like more information let me know. 
Thanks.