New Posts New Posts RSS Feed: Supporting Multiple Persistence Managers
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Supporting Multiple Persistence Managers

 Post Reply Post Reply
Author
Customer View Drop Down
Senior Member
Senior Member
Avatar
User Submitted Questions to Support

Joined: 30-May-2007
Location: United States
Posts: 260
Post Options Post Options   Quote Customer Quote  Post ReplyReply Direct Link To This Post Topic: Supporting Multiple Persistence Managers
    Posted: 12-Jul-2007 at 5:10pm
I really need to test and to learn how to declare two persistence managers in the same application.
 
I agree with you that most of the time it is not a good idea to use two persistence manager but some time, it is necessary in order to have a form or a method running on its own without interfering with whatever else could be running at the same time ... and that is exactly the situation I have.
Back to Top
IdeaBlade View Drop Down
Moderator Group
Moderator Group
Avatar

Joined: 30-May-2007
Location: United States
Posts: 353
Post Options Post Options   Quote IdeaBlade Quote  Post ReplyReply Direct Link To This Post Posted: 12-Jul-2007 at 5:12pm
You're lin luck.  Another customer asked the very same question recently.  Here is the answer from our UI Architext.

Maybe I'm missing something but I don't think it is as hard as it at first appears.

I would NOT keep a list of entities as they change. There is no object eventing required. The "bolt-on" is minimal. You don't have to worry about where you go or what entities are touched within the context of an edit window.

You may pay a small performance penalty for re-reading entities from the database that you are holding in your main PM cache. I say "small" because I assume that the a side-effect of an edit window is a greatly narrowed object scope and, as I remember, you have a fat connection to the data source.

Typically you are editing one root object and some part of its graph. This is usually a small amount of data.

[We can finesse this if my assumptions are wrong. This is the kind of performance tuning that is easy to postpone as it has no bearing on the fundamentals proposed here.]

There is a risk of overlap among the object graphs residing in multiple contexts (e.g., the same vendor in multiple dialogs). That is why we generally prefer modal dialogs to non-modal dialogs.

If you are willing to deal with the concurrency issues WITHIN the client-side application - including the possibility that what the user regards as the same entity will appear differently in different edit windows

- then it is not hard at all.

==========

Here's the game plan:

1) When you open a dialog (after double-clicking a grid row), you start a new PM. This PM sets the context for all changes within that dialog.

2) If you have modal dialogs WITHIN this dialog, you can use CheckPointing to provide OK/Cancel functionality. The PM sets the scope for the CheckPointing levels. I'm assuming that the PM in the dialog sets the context for the child, modal dialogs, if any. CheckPointing is the way to go within a context bounded by a PM.

3) If the user cancels out of the dialog, you simply discard everything in the dialog's PM. This will have no impact on anything going on in any other PM including the main PM holding the grid from which you launched this dialog.

4) If the user presses OK, you will try to save everything in the dialog's PM.

5) You "merge" the saved changes back into the main PM.

---

Here's where a little cleverness is required. You attach a handler to the PM's Saving event (which you do anyway, for validation purposes).

When raised, you will receive a list of every entity the PM thinks it should save. Hold on to that list and make a parallel list of each member's RowState (so you know which are added, modified, or deleted -- the successful save will change the RowStates so you want to remember them as they were <<before>> you saved).

If the Save succeeds, you want to update the main PM's cache from this changed list.

There are various approaches but the most safe and minimal is to refresh those entities in the main PM that are in your dialog change list, e.g.:

A) Add to the main PM anything you added in the dialog.

B) Remove from the main PM everything that you deleted in the dialog.

C) "Refresh" anything in the PM that is shown to be modified in your dialog list.

The "add" and "refresh" can be done with the "import entities" approach that David mentioned. If you have good access to the database and the list isn't huge, I'd probably just refresh from the database but it is up to you.

OK this is not utterly trivial. You have to iterate over your changes list.

A brute force approach would take each one in turn. It is likely that the list is small so you'd be wasting time striving for clever grouping by kind-of-change or entity type. Just walk the list and follow the rules above.

You can always optimize later (e.g. gather all objects of the same type and re-fetch them from the datasource in one-shot).

I can write a utility for the purpose if you need me to do so. The whole process - steps #1 - #6 - should fit nicely into a helper class of some sort.

---

6) When you are done, you should clear the PM in the dialog and then close it. You don't want to leave anything behind that could get out of sync.

-------------------------------

In-Client Concurrency Dangers

-------------------------------

The gravest apparent risk is that there is an overlap between the objects changed in one dialog and their "cognate" objects in another dialog or in the main grid from which you launch the edit windows.

You can think of each PM as if it were a separate client user. Client's don't see each other's pending changes and only see the saved changes when they refresh.

In my view, the danger is that you can confuse the user. This is another reason to prefer model dialogs. On the other hand, you may be able to shape the UI so that the conflict is unlikely and the reason for it (if detected) is clear and acceptable.

---

The difference between the changed entities in the Dialog and the state of cognate entities in the main PM is a kind of concurrency conflict. The resolution is easy: the dialog's copy always wins.

What about conflicts BETWEEN dialogs? If Dialog 'A' changes the vendor and Dialog 'B' changes the same vendor, the first one to save will win; the second one should fail the <<database>> concurrency check while trying to save to the database. This may mean that Dialog 'B' can only cancel ... in which case there is no danger of an in-client conflict (see step #3 above).

[BTW, you mentioned some kind of soft-lock technique that was supposed to address this at the database level. Is there some reason why you wouldn't use the same approach in your client UI?]

Suppose you force dialog 'B' changes into the database somehow. You have to decide how to play the dialog 'B' changes back to your main PM.

This could be trivial: you treat it the same way you did for Dialog 'A'. A successful save of <<any>> dialog's changes always results in a unilateral update of the main PM.

==========

Notice there is NO change tracking at the object level. You are relying on the PM's saving event to tell you what it thinks will be saved. You make a simple copy of this into your own list (step #4) and you're good to go.

===

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down