On 29 Lis, 20:53, Michael Bayer <[email protected]> wrote:
> On Nov 29, 2011, at 2:35 PM, Łukasz Czuja wrote:
>
> > Hello,
>
> > I'm trying to figure out a way to use Session.merge(o, load=False), on
> > an object which is not bound to a session (Session.remove() used after
> > the object was modified, but the changes were not commited).
>
> > When the object's state is modified (instance_state(o).modified ==
> > True) the session merge will fail with:
>
> > "merge() with load=False option does not support objects marked as
> > 'dirty'.  flush() all changes on mapped instances before merging with
> > load=False."
>
> > So i need an rollback(o) on this object only. It might also be a good
> > idea to add an argument to merge() to do just that.
>
> load=False is only a performance optimization.  If you're passing it dirty 
> objects, the optimization cannot take place and guarantee consistent data.   
> It's not feasible for SQLAlchemy to "roll back" the attributes on an object, 
> as it quickly gets into edge cases regarding references and collections where 
> only the view from the relational database can really provide an accurate 
> picture; that's why objects are fully expired, so that attributes can be 
> refeshed from the database on access, instead of "rolled back".

That actually makes more sense. Haven't thought about references, good
point.

>
> You'd have to figure a way to produce a clean object for merge() in the first 
> place if you'd like to avoid its state being reconciled with that of the 
> database.   This is something that's outside the scope of what the ORM 
> provides.
>
> If it were me I'd not be using load=False for any use case other than plain 
> vanilla retrieval from a cache.  If you want to optimize merge() for a 
> non-caching use case, pre-load the full set of objects that you expect to 
> pass to merge() using a series of SELECT statements, then ensure those 
> persistent objects remain referenced.  When you merge in your dirty, detached 
> objects, the state on those objects will be reconciled with the object 
> already in the identity map, and no SQL will be emitted.

I use a more naive approach now, I just assume that objects exist, and
if commit throws an error, I shall reload the problematic rows. For
now I will use:

o = db_session.merge(o, load = instance_state(o).modified)

I do not keep them forever, they expire or get reloaded, whichever
comes first.

Thanks for the insight

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to