Re: [Modeling-users] Foreign Keys
Status: Abandoned
Brought to you by:
sbigaret
|
From: Sebastien B. <sbi...@us...> - 2003-07-21 22:26:20
|
Replying to my own post, I'd like to share some additional informations:
I wrote:
> Now back to your specific problem: based on your code, I assume you have
> the following model:
>=20
> master <--->> i18n (-> is to-one, ->> is to-many)
>=20
> So you'll do something like this, assuming that the master entity's name
> is 'Master' and the relationship' name i18n--->>master is: 'master'
> and the inverse is 'i18ns':
>=20
> >>> i18n =3D I18N()
> >>> ec.insert(i18n)
> >>> master=3Dec.faultForRawRow(masterSnapshot, 'Master')
> >>> i18n.addObjectToBothSidesOfRelationshipWithKey(master, 'master')
> >>> ec.saveChanges()
>=20
> or its alternate equivalent:
>=20
> >>> i18n =3D I18N()
> >>> ec.insert(i18n)
> >>> master=3Dec.faultForRawRow(masterSnapshot)
> >>> master.addToI18ns(i18n)
> >>> i18n.setMaster(master)
> >>> ec.saveChanges()
>
> Naturally, this implies that the 'master' object is fetched and
> initialized within the EditingContext.
Each of these approaches triggers in fact two faults:
1. the fault for object 'master', which is fetched as soon as
addToI18ns is called (triggered by self.willRead()),
2. the fault for master.i18ns (array), which is fetched as soon as
addToI18ns() appends the new object to the array.
In this particular situation, there is a third way of doing this. It
should be considered as a 'hack' to be used in controlled situations
(for example, in batches where you exactly know what has happened
before), because of the limitations discussed below. However and given
these restrictions, it can accelerate the change:
>>> i18n =3D I18N()
>>> ec.insert(i18n)
>>> master=3Dec.faultForRawRow(masterSnapshot)
>>> if master.isFault() and ec.parentObjectStore().__class__=3D=3DEditingCo=
ntext:
... i18n.setMaster(master)
... else:
... i18n.addObjectToBothSidesOfRelationshipWithKey(master, 'master')
>>> ec.saveChanges()
What happens here? The difference here is that when most of your masters
are faults, then you'll avoid to initialize both the masters and their
i18ns.
It works here because of two reasons: this is a toMany relationship,
and we know from the model that the information used for both
relationships 'master' and 'i18ns' is ultimately stored in the foreign
key of table I18N, nothing more. When the master object is a fault,
it's not initialized yet, and knowing that its relations are about to
change does not add anything compare to: just wait until it's needed,
where it will get its related objects, based on the information stored
in the I18N's FK.
(I hope I succeeded in making this clear)
However, I strongly suggest not to remove the test 'if
master.isFault()...', because if for some reasons the master object was
already fetched (believe me, it can happen and surprise you in your own
code ;) this would lead to an inconsistency in the graph of objects
(i.e. master object's i18ns array not being updated where it should be)
The second test checks that the ec is not nested (see
http://modeling.sf.net/UserGuide/nested-ec-dev-hints.html). If it is
nested, I suspect (even if I did not check it explicitely) that
there are particular situations in which the parent's graph of
objects could become inconsistent when the child save its changes.
Last, it should *never* been used in a multi-threaded environment,
because too much thing can happen between the moment where the changes
are made and the time saveChanges() is called. All these precautions
are what I previously called a "controlled environment". May I suggest
that this gets somehow specifically documented in your code if you use
this, so that anyone else working on your code does not get bitten by
this in 2 years, 2 months or 2 days?-)
(I initially wondered whether this should be shared after all, because
of all this, but I think it might come in handy for particular
situations, and that it cay also highlights some particular aspects of
the framework).
You can then verify that you won't get into trouble. For example, if
you then trigger the two faults, master.geti18n() will contain the new
one, as expected.
-- S=E9bastien.
|