I addressed this issue the way I described earlier, that upon setting up a relationship with "delete-orphan", a flag is tacked onto that relatoinship's mapper that "orphans should be deleted" regardless of the presence of any collection with which to cascade from.
Also, I did temporarily establish the rule we discussed where save()- ing an orphaned entity will immediately raise an error; however, this is incompatible with the "contextual session" since the entity is added to the session upon construction and would render it impossible to create new entities. you can see the commented-out check in the changeset if youd like to uncomment it for experimentation. what does happen now if you save() an orphaned entity is that it just doesnt get saved. we could try to put the check further down at flush time perhaps. also, an interesting effect that I didnt think of came up from this, which is that you now no longer can declare a "delete-orphan" cascade rule on a self-referential relationship....since the root of a tree structure is always an orphan. (of course, you could have a circularly-linked structure, which probably requires the post_update flag to be set; but i think that case is fringe enough that folks could handle the deletes manually in that case.) so check out the changeset, which includes the two new tests in a new session.py unit test module: http://www.sqlalchemy.org/trac/changeset/1807 On Aug 18, 2006, at 12:18 AM, Daniel Miller wrote: > > Michael Bayer wrote: >> On Aug 17, 2006, at 5:58 PM, Daniel Miller wrote: >>> Suggested behavior: >>> instead of immediately registering objects that are added to a >>> collection >>> as "new", the registration should be deferred until the session >>> is flushed. >>> On session.flush() any object "u" with a non-persistent child "a" >>> and a >>> cascading save rule will cause "a" to be persisted at that time. >> Keep in mind this approach, for which there is a patch attached >> for you to try out, > > Thanks, I'll try it out and let you know what happens. > >> would behave inconsistently as compared to a setup that is using a >> contextual session, where objects get saved to the session >> unconditionally upon construction (i.e. cascade is more or less >> superfluous). this errant behavior would still remain in that >> case. > > Yes, and in my opinion that's fine. I think only fairly simple > things can be done with that fully automatic save behavior (it's > making a lot of assumptions that don't always hold up in more > complex situations), and edge cases like this will either require > an explicit delete() or a switch to a manual save mode. My use case > doesn't really apply in the case of an automatic save() because I'm > dealing with a User instance that has been registered as new > (saved) and an Address instance that is transient (not saved). > > Actually Hibernates "inverse=True" marker on relationships is > starting to look even better now (you may remember that I had > brought that up in another thread). In this case collection > membership is controlling child object persistence. i.e. > > a = Address > u.addresses.append(a) # "a" is now "new" (marked for save) > u.addresses.remove(a) # "a" is now "transient" (marked for delete) > > Note that this is only useful in some situations and therefore the > inverse=True marker would be handy to tell SA which end of the > relationship is controlling the lifecycle of new/deleted objects. > >> the idea that I had about the unit of work, long ago, was that >> everything could be inside of it, and it would figure everything >> out; insuring that certain objects dont go into the session at >> all as a method of insuring the correct flush operations wasnt >> part of the plan, since that puts extra responsibilities on the >> programmer to make sure only the "right" objects go into the >> Session, and as you know there wasnt really any way to even do it >> back then since everything was threadlocal. > > I'm starting to change my mind about the suggested behavior I had > listed in the test case. If list membership is really controlling > whether an object is persistent or transient, then that suggested > behavior might be wrong. How about this instead: > > If collection membership denotes the lifecycle of related objects > then an object "addr" is registered as "new" in the session when > "addr" is added to collection "u.addresses" and is registered as > "deleted" when "addr" is removed from "u.addresses". > > This differs from my original suggestion in that it does not defer > the association with a session until flush(). Instead it just > balances the new registration with a corresponding delete > registration on append() and remove() respectively. How does that > sound? > >> Hibernate's model is very different from this, and its a lot less >> "smart" about these kinds of things (which is not completely a bad >> thing). such as today I noticed if you save() the same object a >> second time in the session, it goofily inserts it again into the >> table, and then upon cascading to associated collections trips >> over itself with inappropriate error messages and such. >> unfortunately we've gone pretty far down the road of "auto-save" >> and this particular issue seems to be extremely difficult to >> detect. Classes that are in an "orphanable child" relationship >> would need to be flagged and get an extra step to make sure they >> have a parent regardless of there being any parent to start with. >> right now, they are only detected as part of the "deleted items" >> of a particular parent's collection (although we are able to >> detect if they've been moved to a new parent). >> just out of curiousity, what do you think should happen if we did >> this: >> session = create_session() >> a = Address() >> session.save(a) >> session.flush() >> note that no User was ever created at all. should the Address be >> saved ? I think it should not, since the Address class is in a >> relationship that says "delete-orphan"; orphaned Address objects >> should not be saved. this would basically be the logic im >> thinking of. deferring the save() cascade doesnt address this >> issue. > > This should raise an exception because the Address instance has > been explicitly saved in the session without an associated User > instance. The cascade="all, delete-orphan" refers to orphaned > objects that once had a parent (i.e. when the parent is deleted, > the children are also deleted), not new objects that never had a > parent (that's an error condition). My example on the other hand > (with my updated suggested behavior) would not raise an exception: > > # case 1 > u = User() > a = Address() > session.save(u) # "u" is now "new" in the session > u.addresses.append(a) # "a" is now "new" in the session > u.addresses.remove(a) # "a" is now "transient" > session.delete(u) # "u" is now "transient" > session.flush() > >> So with regards to the "deferred save" approach, this is a >> fundamental behavior change and its not clear at all to me if >> existing applications are going to play well with it; as their new >> objects are now not in the session until flush. it also could >> create confusion as turning on "threadlocal" makes a bigger >> difference now. and im not sure if its even the right way to go >> since it doenst fully enforce the "orphaned" relationship >> semantics. (on the other hand, it might be good enough for now). > > The more I think about that deferred save suggestion the more I > think it could cause problems and confusion. I think we just need a > way to tell a collection that "when I append an object it should be > saved and when I remove an object it should be deleted", and a way > to turn that behavior off when it is not wanted (i.e. inverse=True). > > I'll still give your patch a try just to see if it works. And I'll > try to work on tests if I have time as well. Good night. > > ~ Daniel ------------------------------------------------------------------------- Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642 _______________________________________________ Sqlalchemy-users mailing list Sqlalchemy-users@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users