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
-~----------~----~----~----~------~----~------~--~---

Reply via email to