On Jul 28, 2007, at 8:46 PM, MuTPu4 wrote:
> > On Jul 28, 11:08 pm, Michael Bayer <[EMAIL PROTECTED]> wrote: >> theres nothing at all wrong with the above; the only adjustments Id >> make are to a. leave a "global" session open for your directory.root, >> and b. remove all "cascade" rules from the "parent" relation (in this >> case using backref=backref('parent', cascade=None), so that when you >> attach the out-of-session Category as a 'parent' to your new >> Category, the child category can get a parent_id value but the parent >> Category object is otherwise unaffected. > I have tried to use global session object for all DB operations > without synchronization and it seems to work perfectly on simple > tests. It remains only to add application-level synchronization. But I > don't quite understand your second advise about cascading. I thought > that in case of using global session object none of Category instances > can be detached. Am I missing something? when you say: c = Category('foo', root) and you then attach 'root' using c.parent = root, a cascade rule associated with the 'parent' relation will attempt to add the newly attached 'root' Category to the local session. Since 'root' is already in a different Session, this will raise an error. so instead, make a local copy of "root" using merge() before using it in a local session. or if not, you can even just associate using the column based attributes before flushing: c = Category('foo') c.parent_id = root.id above, you arent attaching any of your "cached" objects to your new Category, just setting the appropriate column-valued elements on it. This way you limit the manipulations to just your new object without modifying your cache's structure or state at all. >> the merge() operation will create a copy of "parent" within the local >> session. It will usually issue a fetch operation from the database >> in order to get the most recent data for the particular Category. > The problem with this solution is that I dont always know the part of > the hierarchy that I want to be in the current session. I am relying > on implicit lazy loads and the client-code may want to access a large > parts of the tree using new session, reattaching all of these nodes > which makes my cache strategy useless. merge() will cascade by default. when you merge() root, it also merge ()s everything currently attached to root (this is also configurable). its actually not that efficient of an operation if your structure is very large. you probably dont need to load very much into your local session though, just whatever gets immediately associated with whatever objects you're flushing. >> From the point of view of my example it would be usefull to decouple > loading/storing API from mapped objects themselfs. If it is possible > it will be usefull opportunity imho. you can work with the objects detached from any session, but when you want to put them into a local Session and save them you need to either put them there, or make copies of them. the whole way unit-of- work tools like SQLAlchemy's ORM function is by keeping track of object state and identity; if we allowed you to put your Category object in your "cache" session A, as well as session B used in a particular request that wants to save data, and session C used in yet another concurrent request that wants to save data, it should be apparent that manipulating the object in all those concurrent threads is going to produce inconsistent and conflicting state between each thread...and manipulation operations are extremely common; for example, when you attach "root" to the new Category "c" via its "parent" attribute, the backref is also appending "c" to "root"'s "children" attribute automatically. theres not really any reasonable option to having local, non-thread-shared copies of the objects which you're manipulating. Also, you've stated that you want lazyloads to occur, so already, you do want load operations embedded into mapped objects. if you didnt want that, you could leave your "cached" objects out of any session entirely. the only thing to follow here is, for all your read-only operations, just use your "cache". for any kind of "im going to save something" operation, just load what you need fresh from the database into a local session, put it all together, and flush. by going through the effort to tailor your application this way you help to guarantee the consistency of your objects and the data that goes into your database. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~----------~----~----~----~------~----~------~--~---