|
All is much easier if you can change to an arbitrary primary key (e.g, a counter or a Guid).
We understand that the other three fields must form a unique combination in the database. You won't be able to save the entity until they are jointly unique. You can check the database at anytime. You can check when the user changes any of these values (by making an asynchronous query of the database). You can wait until save ... where you may have to fail the save attempt and ask the user to fix the problem.
Only you know whether it is wiser to determine availability up front or can afford to check later.
If you cannot change the primary key, you'll have to do some kind of validation up front.
The second approach - "gathering the information, then creating the entity" - could be interpreted in two ways.
A) Create an entire UI-oriented entity surrogate (aka ViewModel) which the user modifies; then validate the combo-ID before creating the real entity and populating it with the values the user entered into the ViewModel/Surrogate.
B) Create a separate object to gather just the three fields that comprise the ID. Evalute this. Once it passes, create the entity, set its ID with the approved three field values, and edit the new entity much as you would an existing entity.
You seem to be thinking about (A) in which case you are correct about the consequences. Were you to write such a ViewModel you would have to map to all of the entity properties, port all validation logic to the ViewModel and reimplement INotifyPropertyChanged and all the goodness baked into the DevForce entity.
Ting is suggesting (B). You first coax the user into settling the issue of ID uniqueness. Once that is out of the way then ... and only then ... do you create the new entity, giving it the approved three-value ID.
This way, once ID unquess is resolved, you can bind to the created OrderOwner entity and benefit from that entity's built-in validation and other behavior.
We are imagining that you might present an "Add OrderOwner" dialog that asks for the three critical pieces of information. This dialog binds to a much simpler ViewModel (e.g., one having just the three properties). The "OK" button results in an asynchronous query to verify that combination is available. You'll use the BusyControl to "freeze" the UI (block user input) until the answer returns.
You get the idea we hope; you relegate the problem to a dialog that concentrates exclusively on the unique-ID problem.
[You must also check to see if the combination Id is in cache. You could make the cache check your only check at this time.
The user wouldn't have to wait for the server to return the answer. The downside is that you may be unable to save the entity later because that Id, while not in cache, has already been registered in the database. Of course that is a potential problem even with the suggested design ... because someone could slip in a new record with that Id between the time you checked and the time you save. Only you know the probabilities.]
Approach (B) makes life easier on you. Will it be good for the user? That's something you have to figure out. I'd be reluctant to take the easy (B) path if that made the user suffer. I'd suck it up and do (A).
---
It occurs to me that you might be able to implement either (A) or (B) using an OrderOwner entity instead of having to write a wrapping ViewModel.
The duplicate primary key problem doesn't manifest itself until you add it to the target EntityManager.
I'm thinking out loud here so bear with me.
You could create another EntityManager that is only used for adding new OrderOwner entities. When the user presses the "Add" button, you create a new OrderOwner ... in this "TempEntityManager". You still have to force the user to make the ID unique (at least locally). You can let the user fill in some of the other properties if you think that is a good idea (I cringe).
Once ID uniqueness is established (which means confirming that this ID is not in the real EntityManager ... as well as not currently in the database) ... you detach it from TempEntityManager and add it to the real EntityManager. The entity retains "object entity" which means that the UI continues to reference the same CLR object. You've just moved the object from one EntityManager to another.
It's a hack ... but it should work. It's less complicated if TempEntityManager is only allowed to hold a single OrderOwner. Let the user add one new OrderOwner, resolve the unique ID issue, then detach and add the new OrderOwner to the "real" EntityManager.
We hope one of these ideas yields a breakthrough for you.
P.S.: PLEASE say that the combination key cannot change once the OrderOwner has been entered into the database. If this is NOT true, you are in big trouble ... especially if related entities refer to this entity by its three-part-key. Do whatever you can to switch to a single, synthetic (arbitrary, meaningless) key and use that for all FK references. You can still insist that the three fields are jointly unique. Just make sure their values are only to be found in the OrderOwner entity.
|