On Jul 28, 5:36 pm, Michael Bayer <[EMAIL PROTECTED]> wrote:
> your best option is probably to keep the objects in a session that's
> specifically for the "global" objects.  Most important is that if you
> are using multiple threads, you never call flush() on this session.
> With regards to threadsafety in this case, as long as the session is
> not used for a flush() operation, you should be OK.  The connection
> used for querying for a non-transactional session is checked out
> distinctly per-operation, so there will be no conflicts there.  The
> second place of concern is when the Query retrieves existing objects
> from the identity map as it loads rows, and as it places newly loaded
> objects into the identity map;  multiple threads might both create the
> same object and might both store it in the identity map; only one
> would actually remain in the map.  However for a purely read-only
> situation, your application will still see the same kinds of objects,
> and even the object that was "replaced", which still would remain
> established in a parent collection, can still call upon that session
> to issue further lazyloads.
>
> I might look into adding a flag in 0.4 session "readonly", which
> produces a session that disallows flush() and places a single mutex
> around query.instances(); then youd have a completely threadsafe read-
> only session.  its only a couple of lines.
Thanks for your replay.
Probably my case is somewhat more compilcated but I thought that it is
rather common. It may be outlined as follows.
I have a long-running application (web server) which resopnds to
frequent queries users (pages fetch). The data is organized into
hierarchical directory which is represented by Nodes and Items:
[code]
    self.categories_table = Table(
        'categories'
      , self.metadata
      , Column( 'category_id', Integer, primary_key = True )
      , Column( 'name', String, nullable = False, index = True )
      , Column( 'parent_category_id', Integer, nullable = True, index
= True )

      , ForeignKeyConstraint( [ 'parent_category_id' ],
[ 'categories.category_id' ], onupdate = 'CASCADE', ondelete =
'CASCADE' )
    )
    self.items_table = Table(
        'items'
      , self.metadata
      , Column( 'item_id', Integer, primary_key = True )
      , Column( 'name', String, nullable = False, index = True )
      , Column( 'parent_category_id', Integer, nullable = False, index
= True )

      , ForeignKeyConstraint( [ 'parent_category_id' ],
[ 'categories.category_id' ], onupdate = 'CASCADE', ondelete =
'CASCADE' )
    )
[/code]
I want to have a global preloaded tree structure for fast access
(frequent reads and infrequent modifications) with application's
lifetime and ability to fetch Items as needed. I wanted to use some
nice automation features of SA's ORM (lazy
loads across relations, automatic DB updates etc) so I have come up
with the following "solution":
[code]
class Category( object ) :
  def __init__( self, name, parent_category ) :
    self.name = name
    self.parent = parent_category

class Item( object ) :
  def __init__( self, name, parent_category ) :
    self.name = name
    self.parent = parent_category
[/code]
[code]
  #data mapping
  self.items_mapper = mapper( item.Item, self.items_table, properties
= {
        'parent' : relation( Category, uselist = False, lazy = False )
  } )
  self.categories_mapper = mapper( category.Category,
self.categories_table, properties = {
        'children' : relation( Category, backref = backref( 'parent',
remote_side = [ self.categories_table.c.category_id ] ), cascade =
'all' )
  } )
[/code]
[code]
  #application init
  session = self.db.create_session( )
  self.root =
session.query( Category ).selectone( Category.c.parent_category_id ==
None )
  session.close( )
[/code]
[code]
  #hypothetical code in one of the threads
  session = self.db.create_session( )
  new_obj = Category( 'test', directory.root )
  session.save( new_obj )
  session.flush( )
  print new_obj.parent.name
  len( new_obj.children )
  subitems = session.query( Item ).select_by( parent_category_id =
directory.root.category_id )
  session.close( )
[/code]
Now I see that this approach is not viable as-is. Maybe there is a way
to adopt it using modules like SessionContext and assignmapper?
If there is no such a way, I currently see two solutions:
1. Just dont use permanent objects and fetch an appropriate portions
of informations at every request relaying on DB's cache and loopback
network optimizations.
2. Using basic SA features implement an ad-hoc ORM as a part of
Category and Item classes which will use given session to fetch/insert/
uopdate data.
Maybe someone can point me to another not so painful solution?


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