On Jan 15, 11:56 am, Tvrtko <qvx3...@gmail.com> wrote: > First, let me say that I'm using sqlalchemy version 0.5.8. We have a > large and complex application and changing to sa 0.6 is expensive, so > I would like, if possible, to find a solution for 0.5. I'm using > sqlalchemy since version 0.1. > > Problem: objects are one moment inside a session an the other moment > are not. > > Setup: > > Session is in weak_identity_map=False mode: > > maker = sessionmaker(autoflush=True, autocommit=False, > weak_identity_map=False, > extension=[ZopeTransactionExtension(), EpiSessionExtension()]) > DBSession = scoped_session(maker) > > All objects are immediately added to session: > > campaign = Campaign(...) > DBSession.add(campaign) > > Plus, the reference to object is kept locally. > Plus, the object is assigned to another relation property: > > qitem = QItem(campaign=campaign, ...) > DBSession.add(qitem) > > Now, the problem occurs at two different random points. Both time > the garbage collector is collecting the garbage before the problem > presents itself. This may have nothing to do with a problem. > > Everything happens inside a single thread. > > First case: > > campaign = Campaign(...) > DBSession.add(campaign) > ... > # called indirectly because of lots of queries > DBSession.flush() > print campaign.id # 206 > > # A: the (<Campaign>, 206) is inside the keys > print DBSession.identity_map.keys() > > contact = DBSession.query(...).one() > # garbage is collected while this runs > # I can see it because of gc.set_debug(...) > # However, campaign is referenced locally and gc > # leaves it, but maybe some other internal SA object > # is collected. > > # B: the (<Campaign>, 206) is no longer present > print DBSession.identity_map.keys()
Actually, this case is the same as the second case, so let's just ignore it. The objects are not expunged from the session without a reason as the example might suggest. Objects are removed because the automatic `flush()` inside `query()` failed and rolled back the transaction (and removed objects from session). "B" print was done inside exception handler. So, it really is the same case as the second one: > Second case, very similar, but problem appears at a later point: > > campaign = Campaign(...) > DBSession.add(campaign) > DBSession.flush() > print campaign.id # 207 > contact = DBSession.query(...).one() > > # Also, assign campaign to relational property of `qitem` > qitem = QItem(campaign=campaign, ...) > DBSession.add(qitem) > > # The (<Campaign>, 207) is inside the keys > print DBSession.identity_map.keys() > > DBSession.flush() # called via commit by web controller > # DB raises exception CONTACT_ID cannot be NULL Somehow, the `qitem.campaign` relation property behaves as if it is not set at all, and SA doesn't prepare `QITEM.CAMPAIGN_ID` properly. > > The exception is raised because the `campaign` object > again got expunged from session for some reason, even > though the `qitem` itself holds a reference to it. Well, maybe it wasn't expunged at that point, I dont have a proof, but the `CAMPAIGN_ID` was set to NULL as if the `campaign` property was not set. -- 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 sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.