On May 1, 2010, at 10:18 AM, Kent wrote: > Is it rude to ask why not disable the weakidentity map? > > Under the turbogears web framework, our Sessions only exist for the > duration of the service call, and I am finding myself appending all > these objects to a "no_garbage_collect" list that I am keeping on the > session object anyway. > > Then the thought occurred "if there are problems, maybe he would have > deprecated disabling the weakidentity map..."
The strong map only exists because it took us a very long time to figure out how to to the "weak" map correctly, as there were two major technical challenges to fix. one was how to not lose dereferenced but "dirty" items, the other was how to avoid the creation of publically-inaccessible cycles between objects and those within their related collections. There's no "problem" with the strong map other than its a configuration switch that adds to potential confusion, and when in use now demands that the Session be used in a very specific way, else the program's memory usage will grow unbounded. The strong map also features a "prune" method that absolutely does not work outside of cPython. So to me its a section of mediocre and unnecessary code that I'd like to remove. I do make "strong" collections for certain loading patterns but I prefer it to be local to a particular set of things that I know will be dereferenced at the end of a method, rather than the whole session. There are also per-session result-caching patterns that are described in examples/beaker_caching which I will sometimes make use of - these have the advantage of caching the whole query execution and fetching procedure, not just the objects themselves, and is also something you set up per-query. Other than that if you truly need everything sent in via add(), merge() and query() to just not go away, I'd rather add an extra method to SessionExtension for that. after_attach() already gets things via add()/delete()/merge() so another method like after_load() would accomplish that for query(). then you could just stick a set() on the session that stores whatever is received. > > > > > On Mar 4, 5:26 pm, "Michael Bayer" <mike...@zzzcomputing.com> wrote: >> Kentwrote: >>> Thanks... that is very helpful. I could keep references to these. If >>> I choose the apparently lazier route and set weak_identity_map=False, >>> then does any other action besides explicitly expunging free this >>> memory, such as when the session goes out of scope, I assume? >>> Or do I need to carefully expunge them? >> >> don't disable theweakidentity map. just maintain your own collection >> of all the objects you care about. >> >> >> >>> On Mar 4, 4:09 pm, Conor <conor.edward.da...@gmail.com> wrote: >>>> Conor wrote: >>>>> Kentwrote: >> >>>>>> I agree I shouldn't care, so maybe there is another way to attack my >>>>>> problem. The reason I care is because I've extended the python >>>> object >>>>>> with some auxiliary information that I need. After the refresh() in >>>>>> this case, I still need access to that data that is tied to the >>>>>> object, but not present in the database (it is transient data). If >>>>>> sqla creates a new instance, I loose that data. >> >>>>>> Is there a better mechanism for doing that? >> >>>>> You need to either manually keep strong references to each object that >>>>> has the auxiliary information or disable theweakidentity map. See >>>>> http://www.sqlalchemy.org/docs/05/session.html#frequently-asked-quest... >>>>> or >>>>> http://www.sqlalchemy.org/docs/05/session.html#frequently-asked-quest... >>>>> for more information. >> >>>> That second link should >>>> behttp://www.sqlalchemy.org/docs/05/session.html#session-attributes. >>>> Oops. >> >>>>>> On Mar 4, 3:38 pm, "Michael Bayer" <mike...@zzzcomputing.com> wrote: >> >>>>>>> refresh doesn't remove any objects from the session so its a matter >>>> of >>>>>>> what is present in the session, not marked as dirty, and strongly >>>>>>> referenced on the outside. if you're using refresh you shouldn't >>>> care >>>>>>> about how it gets data back into the collection. >> >>>>>>> Kentwrote: >> >>>>>>>> What's strange is that I can't recreate the problem on more simple >>>>>>>> stage. Every time I refresh() on the parent object, the list >>>> objects >>>>>>>> remain the same. In other words, *sometimes* it behaves as I hope >>>> it >>>>>>>> to (by apparently refreshing the list's objects) and *sometimes* if >>>>>>>> throws them out and creates new ones. The mystery to me is what >>>>>>>> determines when it will create new instances vs. refreshing the >>>>>>>> existing ones? >> >>>>>>>> On Mar 4, 3:24 pm, "Michael Bayer" <mike...@zzzcomputing.com> >>>> wrote: >> >>>>>>>>> Kentwrote: >> >>>>>>>>>> If I use session.refresh(obj) to re-load an obj that has a >>>> one-to-many >>>>>>>>>> relational property, the objects in the list are *replaced* >>>> instead of >>>>>>>>>> *refreshed* if they already exist. >> >>>>>>>>>> Suppose department has a list of employees: >> >>>>>>>>>> suppose dept.employees = [ emp1, emp2 ] >> >>>>>>>>>> session.refresh(dept) >> >>>>>>>>>> the dept."employees" list's elements are replaced with new >>>> objects >>>>>>>>>> instead of reusing those that existed and refreshing them. >> >>>>>>>>>> Is it possible to have those same objects re-used and simply >>>> refreshed >>>>>>>>>> instead of replaced? >> >>>>>>>>> you can only turn off "refresh-expire" cascade, which will >>>> prohibit the >>>>>>>>> operation from traveling into the child objects. the collection is >>>>>>>>> still >>>>>>>>> refreshed for obvious reasons, its one of the attributes on your >>>> mapped >>>>>>>>> object. >> >>>>>>>>> To achieve your specified behavior, use session.refresh() given as >>>> its >>>>>>>>> second argument the set of attribute names which are safe to be >>>> reloaded >>>>>>>>> completely (in this case the scalars). Then for each uselist >>>>>>>>> attribute, >>>>>>>>> iterate the collection of each and call the desired version of >>>>>>>>> session.refresh() for those. >> >>>>>>>>> This is an easy refresh() function to create in a generalized way >>>> by >>>>>>>>> inspecting the class-level attributes of the incoming object. >> >>> -- >>> You received this message because you are subscribed to the Google Groups >>> "sqlalchemy" group. >>> To post to this group, send email to sqlalch...@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 sqlalch...@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 sqlalch...@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.