On Thu, Jan 17, 2013 at 3:54 PM, Michael Bayer <mike...@zzzcomputing.com>wrote:
> > On Jan 17, 2013, at 6:45 PM, Ken Lareau wrote: > > Sadly, it looks like when I try the code in my full application, it is > failing miserably. > I'm seeing errors like this: > > sqlalchemy.orm.exc.DetachedInstanceError: Instance <Deployments at > 0x3367910> is not bound to a Session; attribute refresh operation cannot > proceed > > and > > sqlalchemy.exc.InvalidRequestError: Object '<HostDeployments at > 0x21cd050>' is already attached to session '1' (this is '3') > > Sadly it's not immediately obvious as to what's going on... not even > certain how > to start debugging this problem. > > > well an object can only be "attached" to one Session at a time. so the > tricky thing is that it's kind of easy to get objects in the Session > sometimes when you don't want them to. like if you have A and B, and > there's a relationship between both like A.bs an B.a, putting an "A" into a > Session will pull in the "B" and vice versa. > > So if you're putting some kind of object into this other Session to be > committed immediately, you'd have to make sure it isn't being pulled into > your primary session. if you call object_session(someobj) on any object > it will show you what Session it belongs to. > > The other option is to merge() the state of the object into another > Session. merge() makes a copy of an object from one Session to another. > Though here you're looking to commit those objects in the second session > and not at all in the first so you probably should jsut make sure those > objects are only in that one Session. > That would explain things, since I have things like: with isolated_transaction(): host_dep.status = 'ok' Session.commit() Obviously the 'host_dep' is from the original session, so this isn't going to work. I know about merge(), though in this case I'm not fully certain how to use it, or if it can even solve issues like this. :( - Ken > > > > - Ken > > > On Tue, Jan 8, 2013 at 2:59 PM, Ken Lareau <klar...@tagged.com> wrote: > >> On Tue, Jan 8, 2013 at 2:16 PM, Michael Bayer >> <mike...@zzzcomputing.com>wrote: >> >>> >>> On Jan 8, 2013, at 4:00 PM, Ken Lareau wrote: >>> >>> >>> Given this and your previous comments, and after some conversations with >>> a coworker, I decided to expose the 'engine' variable from the database >>> library and create a context manager as so: >>> >>> @contextlib.contextmanager >>> def isolated_transaction(NewSession=None): >>> """Manage a new transaction (session) within an existing session""" >>> >>> needed_session = True >>> existing = Session.registry() >>> >>> if NewSession is None: >>> NewSession = scoped_session(sessionmaker(bind=engine)) >>> else: >>> needed_session = False >>> >>> Session.registry.set(NewSession) >>> >>> try: >>> yield >>> finally: >>> Session.registry.set(existing) >>> >>> if needed_session: >>> NewSession.close() >>> >>> >>> (This code hasn't quite been tested yet and may need some tweaking) >>> With this, whenever I need an 'isolated' transaction I can simply do >>> from my program: >>> >>> with isolated_transaction(): >>> <do stuff with Session> >>> >>> And things should 'just work'... at least that's my hope! I can also >>> pass >>> an existing new session if I want to use one in multiple places (not >>> sure I'll need that just yet, but it was easy enough to write into the >>> method, so...) >>> >>> Hopefully this seems like a sane solution to my problem. :) >>> >>> >>> its good, though you can save yourself all the trouble with >>> scoped_session/sessionmaker by just saying this: >>> >>> from sqlalchemy.orm import Session >>> new_session = Session(bind=engine) >>> >>> or which might be even more portable, use the sessionmaker from your >>> existing registry: >>> >>> new_session = Session.session_factory() >>> >>> session_factory is the sessionmaker() you stuck onto scoped_session in >>> the first place. In that case you don't need to refer to the Engine >>> explicitly. >>> >> >> Nice, the second one definitely works and I no longer need to export >> 'engine' >> and only need to import Session from my library where I have the context >> manager place. :) >> >> Thanks again! >> >> - Ken >> >> >>>>> Depending on the database in use, using low isolation levels can have >>>>> the effect that other transactions can view "dirty reads" as the >>>>> transaction proceeds, but this is obviously an all-or-nothing thing. >>>>> When I need certain resources exposed during a long running transaction, >>>>> I >>>>> transfer that data to a different Session and commit() those changes >>>>> distinctly. >>>>> >>>>> My current needs would tend to use the short transactions for things >>>> that are mostly >>>> isolated from anything going on in the longer running (main) >>>> transaction, though I do >>>> suspect I might need what you mention in your last sentence, but might >>>> you be able >>>> to refer me to an example of how it would work, perchance? >>>> >>>> >>>> I'd advise against going this route, you'd pretty much need to use >>>> MySQL MyISAM tables to get guaranteed "dirty reads", that is, there's no >>>> transaction at all, and it's not really how transactions were meant to be >>>> used. Lowering the isolation level is usually just a means to get more >>>> transaction throughput. >>>> >>> >>> Okay, I suspect I misunderstood what was being mentioned here, which is >>> no problem; I'll avoid it. :) Thanks once again for all the help. >>> >>> -Ken >>> >>> >>>> >>>> -- >>>> 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. >>>> >>> >>> >>> >>> -- >>> - Ken Lareau >>> >>> >>> -- >>> 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. >>> >>> >>> >>> -- >>> 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. >>> >> >> >> >> -- >> - Ken Lareau >> >> > > > -- > - Ken Lareau > > > -- > 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. > > > -- > 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. > -- - Ken Lareau -- 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.