On Tue, 2003-02-04 at 23:26, Andriy Shapochka wrote:
> I started to implement support of flattened relationships in CommitContext and, in the process, a couple of probably important questions to the current implementation have arisen.
> Let's say we have:
> ObjEntity A;
> ObjEntity B;
> flattened ObjRelationship AtoB;
> flattened reverse ObjRelationship BtoA;
> DataObject a; of type A
> DataObject b; of type B
>
> Scenario:
> 1) a.addToManyTarget("AtoB", b, true);
> 2) b.removeToManyTarget("BtoA", a, true);
> 3) b.addToManyTarget("BtoA", a, true);
>
> After these three actions we must have had exactly one registered flattened relationship between 'a' and 'b' in
> the data context, since setReverse == true.
> But it looks like the current implementation does not unregister flattenedInsert in the data context after 2). > And then 3) registers the relationship between 'a' and 'b' once more. As a result the following commit will try
> to insert two identical records into the intermediate relating table.
> What do everybody think? We could try and deal with this problem at
> commit-time but I think this behavior is inconsistent by itself. If so
> maybe I should try to rewrite the registration/unregistration code.
You are indeed correct. The registration process
(registerFlattenedRelationshipInsert and
registerFlattenedRelationshipDelete) should be smarter. Registering a
delete when there's a corresponding insert should just remove the
insert. And vice-versa. I'll fix it up, given that it's my fault in
the first place :-).
>
> One more thing, if setReverse == false in addToManyTarget a flattened relationship does not get registered
> in the data context and as a result the consequent commit does not
> insert a record into the table-intermediary that is the relationship
> is not saved in the database at all. Am I correct? This also seems to
> be inconsistent.
Yeah, it's messy, hence the comment in the code:
//Only create the internal object if we should "setReverse" (or rather,
if we aren't not setting the reverse).
//This kind of doubles up the meaning of that flag, so we may need to
add another?
It works in the "normal" case, where the client is using the
code-generated methods for accessing the property. However, as per the
comment, perhaps we need a better way of determining when to create the
intermediate record. Essentially I shied away from it initially because
I couldn't see a clean way to do it, and it didn't seem like it would
likely be an issue. Basically we need a way to only register the
flattened insert once, not when adding to the reverse relationship. An
interesting thought here: Given that the link tables must (by
definition) have a pk of the combined pk's of the related objects, a
given pair of objects A,B can only ever have one link record if db
integrity is to be maintained. If we take the fix to the first problem
(above) to the natural conclusion, we simply do not allow the same link
to be created twice (we ignore the second registration because it's
already been done). Then the setReverse clause of the if-statement
around the register operation is unnecessary.
Can anyone see an issue with this resolution? It's not quite as
efficient, but is more correct.
(Oh, and this will have to apply to removeToManyTarget too)
Craig
This archive was generated by hypermail 2.0.0 : Tue Feb 04 2003 - 14:38:14 EST