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.

Reply via email to