this patch will cause the mapper to reload all the properties in
identity-mapped objects every time a SELECT statement comes across
it, blowing away any changes that might have been made to the object
in memory. it maintains the unique per-session identity map of
instances:
Index: lib/sqlalchemy/mapping/mapper.py
===================================================================
--- lib/sqlalchemy/mapping/mapper.py (revision 1215)
+++ lib/sqlalchemy/mapping/mapper.py (working copy)
@@ -308,6 +308,7 @@
return self._get(key, ident)
def _get(self, key, ident=None, reload=False):
+ reload = True
if not reload:
try:
return objectstore.get_session()._get(key)
@@ -815,6 +816,7 @@
# look in main identity map. if its there, we dont do
anything to it,
# including modifying any of its related items lists, as
its already
# been exposed to being modified by the application.
+ populate_existing = True
identitykey = self._identity_key(row)
sess = objectstore.get_session()
if sess.has_key(identitykey):
Alternatively, this patch blows away the Identity Map entirely.
this patch is the most equivalent to the feature youre looking for,
i.e. disabling all "caching". definitely worth trying:
Index: lib/sqlalchemy/mapping/unitofwork.py
===================================================================
--- lib/sqlalchemy/mapping/unitofwork.py (revision 1215)
+++ lib/sqlalchemy/mapping/unitofwork.py (working copy)
@@ -70,6 +70,10 @@
def create_list(self, obj, key, list_, **kwargs):
return UOWListElement(obj, key, list_, **kwargs)
+
+class DoNothingDict(dict):
+ def __setitem__(self, key, value):
+ pass
class UnitOfWork(object):
"""main UOW object which stores lists of dirty/new/deleted
objects, as well as 'modified_lists' for list attributes. provides
top-level "commit" functionality as well as the transaction
boundaries with the SQLEngine(s) involved in a write operation."""
@@ -77,7 +81,7 @@
if identity_map is not None:
self.identity_map = identity_map
else:
- self.identity_map = weakref.WeakValueDictionary()
+ self.identity_map = DoNothingDict()
self.attributes = global_attributes
self.new = util.HashSet(ordered = True)
@@ -142,8 +146,8 @@
def _validate_obj(self, obj):
"""validates that dirty/delete/commit operations can occur
upon the given object, by checking
if it has an instance key and that the instance key is
present in the identity map."""
- if hasattr(obj, '_instance_key') and not
self.identity_map.has_key(obj._instance_key):
- raise InvalidRequestError("Detected a mapped object not
present in the current thread's Identity Map: '%s'. Use
objectstore.import_instance() to place deserialized instances or
instances from other threads" % repr(obj._instance_key))
+# if hasattr(obj, '_instance_key') and not
self.identity_map.has_key(obj._instance_key):
+# raise InvalidRequestError("Detected a mapped object not
present in the current thread's Identity Map: '%s'. Use
objectstore.import_instance() to place deserialized instances or
instances from other threads" % repr(obj._instance_key))
def update(self, obj):
"""called to add an object to this UnitOfWork as though it
were loaded from the DB,
feel free to play around with either of these. I am not opposed to
adding switches to put these into effect, on a global or per-mapper/
per-session basis; however I dont have the resources to support
issues related to side-effects of these modifications, since its
essentially a different ORM.
On Mar 26, 2006, at 3:36 PM, Michael Bayer wrote:
theres no caching in SQLAlchemy. theres an identity map which has
some of the same effects as a cache. basically, if you have
already loaded your object into the current session, thats it. if
you load it again, its going to use the same one you have, unless
you clear the session, or refresh/expire the object. SA is not
going to make a random guess as to what objects you want refreshed
and which ones you are expecting to stay linked to the current
editing session, which changes you want to keep and which ones youd
like to discard.
consider this scenario: you load object A and object B into the
current session. objects A and B have state information that is
highly interdependent. you then make changes on B which depend
highly on the current state of A. Then some functions are called
to do some not totally related tasks. As a matter of course,
within those function calls some other part of the application
makes a select statement which also requests "A", which has now
been modified in the database by another process.
returning from the function, A has been magically updated by an
unknown actor, and B is now in an invalid state against the new
version of A. the application breaks.
the point of the identity map is to prevent the above scenario, and
the myriad of variations on it, from occurring. you are assured
that every object, once loaded into the session, will not change
unexpectedly without your say-so, and because their identity is
assured, all changes made to that object identity are reflected
consistently throughout the editing session; its state will always
be consistent within the session. if you need multiple copies/
states, then you use multiple sessions, or pick and choose who
should be refreshed.
if you havent already, I totally overhauled the unit of work
documentation yesterady in response to the recent spate of
confusion over what an identity map and a unit of work is used for
- http://www.sqlalchemy.org/docs/unitofwork.myt . It also details
the refresh/expire/expunge methods as well as "per-object sessions"
which may also provide a way for you to get fresh copies (i.e.
myobj = mapper.using(Session()).get(1) will always be fresh...and
unsaveable unless you import it into another session since the
original one falls out of scope)
also, I would recommend Fowler's "Patterns of Enterprise
Architecture" which is where I learned about all these patterns:
http://www.martinfowler.com/books.html#eaa . SQLAlchemy's ORM is
a python version of the "unit of work", "data mapper", and
"identity map" patterns described in this book. If those arent the
patterns you want to use, its going to be more of an uphill battle
trying to make SA be something its not....but even then, it is
possible, youd just have to write a layer on top of it to provide
the patterns youre looking for (or write an ORM on top of the SQL
construction facilities).
On Mar 26, 2006, at 1:33 PM, Florian Boesch wrote:
Seemingly SA is fairly liberal with interpreting my wish to get
stuff from the
database.
So what's the pattern to deal with "session" "caching"?
I hear there's expunge etc. now, and expire, but that's all when I
know what
objects I want to have removed/expired/refreshed. Fact is, I
don't, I wouldn't
ask for an object from the database when I already had that very
object...
So is there a way to end a session by force?
Can I disable all caching?
How do I deal with that?
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting
language
that extends applications into web and mobile media. Attend the
live webcast
and join the prime developer group breaking into this new coding
territory!
http://sel.as-us.falkag.net/sel?
cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting
language
that extends applications into web and mobile media. Attend the
live webcast
and join the prime developer group breaking into this new coding
territory!
http://sel.as-us.falkag.net/sel?
cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
Sqlalchemy-users mailing list
Sqlalchemy-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sqlalchemy-users