Oh, i would never recommend turning off the identity map....the second patch below is more for educational means, which is why I say its "definitely worth trying" - I was amazed at how fast things started to break down when i tried it. having the mapper re-fetch the attributes on every select is more innocuous, so I threw in an option for it, although I wouldnt recommend using that option either as it dilutes the advantages of session-based development.
On Mar 26, 2006, at 11:22 PM, Jonathan Ellis wrote: I'm really suspicious of this because the other ORM whose design I really admire, the Java SimpleORM, also has an identity map with no way to turn it off, and its author has put a hell of a lot of thought into it. FWIW.
On 3/26/06, Michael Bayer <[EMAIL PROTECTED]> wrote: 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
-- Jonathan Ellis http://spyced.blogspot.com |