Re: Flattened Relationships revisited

From: Craig Miskell (cmiskel..lbatross.co.nz)
Date: Tue Feb 04 2003 - 14:37:46 EST

  • Next message: Andriy Shapochka: "Re: Flattened Relationships revisited"

    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