On Dec 28, 2007, at 4:20 AM, Max Ischenko wrote:

> class DatabaseFacade(object):
>      ...
>     session = property(fget=lambda self: Session())
>
> Session is setup as:
> Session = scoped_session(sessionmaker(autoflush=True,  
> transactional=True))
>
> and configured later on.
>
> Here is how I use it:
>
>     def create_draft(self, **kw):
>         p = WordpressPost(**kw)
>         self.session.save(p)
>         self.session.commit()
>         return p
>
> Since self.session is a property it calls Session() repeatedly. It  
> seems to work but is it OK, from transactional/performance point of  
> view?

since Session is scoped, its automatically a threadlocal.  you could  
just say:

class DatabaseFacade(object):
    session = Session

the transaction "commit" inside the create_draft method is a little  
strange.  usually, if you have a long running transaction, there would  
be a begin()/commit() pair framing a series of operations.  issuing  
commits inside of method sets seems to imply you dont really want a  
"transactional" session....but the session begins the next transaction  
lazily so theres probably nothing terrible about doing it that way.


> Do I need to change it to something like:
>         s = self.session # obtain new session
>         s.save(p)
>         s.commit()
>

nah, with scoped_session you really arent using a "new" session in any  
case, its all the same underlying session object bound to the thread.   
you only get a "new" session if you were to first say Session.remove().


> I also noticed that session.save() fails if I try to save a  
> "persistent" object so I am forced to change every such save() call  
> to save_or_update(). I don't mind but why it's not mentioned in  
> whatsnew40/migration guide?

well that has always been the rule, it was just never enforced...that  
was a new change in 0.4.1.  the stricter session behavior is mentioned  
in the 0.4.1 CHANGES.

> Another error I am now getting is:
> InvalidRequestError: Instance '[EMAIL PROTECTED]' is with key  
> (<class 'doupy.model.objects.Invoice'>, (73L,), None) already  
> persisted with a different identity
>
> Any ideas how to fix this?

it depends on how you are getting there.  it means there is already an  
Invoice object with the same _instance_key in the session. to create  
this error, do this:

s1 = create_session()
s2 = create_session()

obj1 = s1.query(MyClass).get(1)
obj2 = s2.query(MyClass).get(2)
s1.expunge(obj1)
s2.update(obj1)  # <-- error

or more low level, you could do it like this:

s1 = create_session()
obj1 = s1.query(MyClass).get(1)
obj2 = MyClass()
obj2._instance_key = obj1
s1.update(obj2)

note that if you are using scoped_session, you have a distinct session  
per application thread.  so if any sharing of data between threads is  
going on, that makes an error like this fairly easy to produce (i.e.  
things can be updated() into the session via cascades along a  
relation(), for example).


> Btw, is it possible to retrieve metadata if you have an engine or  
> configured session object? I haven't found a way so ended up storing  
> it in a module global when session is configured.

MetaData is usually a module global, its attached to tables also....so  
for example class_mapper(AnyMappedClass).mapped_table.metadata



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