Discussion:
[sqlalchemy] Merge instances of objects without dropping attributes that are not persisted
Ruben Di Battista
2018-04-02 20:29:03 UTC
Permalink
Hello,

I have some SQLAlchemy-persisted instances of objects that have some
relationships coming from a parallel execution with multiprocessing. When I
reduce the results coming from the several processes, I need to merge some
relationships (`satellite` and `ground_station` objects in the code below)
since the associated object got another instance id during the
multiprocessing execution and if I don't merge I get an error like this:

sqlalchemy.exc.InvalidRequestError: Can't attach instance <Satellite>;
another instance with key <...> is already present in this session

Below the code responsible of this (where results is the reduced list
coming from the multiprocessing execution)

for passage in results:
# I need to merge since if coming from multiprocessing the instance
# IDs change.
passage.satellite = session.merge(passage.satellite)
passage.ground_station = session.merge(passage.ground_station)
session.add(passage)


This was working as expected when an attribute `satellite.tle` was
persisted in the database. I was asked now to remove that persistence from
the DB. So that attribute is present at runtime, but it's not in the
columns of the DB. `session.merge` now returns an objects where that `tle`
attribute is not present anymore.

So in the call:
passage.satellite = session.merge(passage.satellite)

the `satellite` object within `session.merge` correctly has the `tle` object,
while the returned object from `session.merge` does not. Is there a way to
avoid that merge strips off the attributes that are not persisted in the
database?
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+***@googlegroups.com.
To post to this group, send email to ***@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
Mike Bayer
2018-04-02 22:10:37 UTC
Permalink
On Mon, Apr 2, 2018 at 4:29 PM, Ruben Di Battista
Post by Ruben Di Battista
Hello,
I have some SQLAlchemy-persisted instances of objects that have some
relationships coming from a parallel execution with multiprocessing. When I
reduce the results coming from the several processes, I need to merge some
relationships (`satellite` and `ground_station` objects in the code below)
since the associated object got another instance id during the
sqlalchemy.exc.InvalidRequestError: Can't attach instance <Satellite>;
another instance with key <...> is already present in this session
Below the code responsible of this (where results is the reduced list coming
from the multiprocessing execution)
# I need to merge since if coming from multiprocessing the instance
# IDs change.
passage.satellite = session.merge(passage.satellite)
passage.ground_station = session.merge(passage.ground_station)
session.add(passage)
This was working as expected when an attribute `satellite.tle` was persisted
in the database. I was asked now to remove that persistence from the DB. So
that attribute is present at runtime, but it's not in the columns of the DB.
`session.merge` now returns an objects where that `tle` attribute is not
present anymore.
passage.satellite = session.merge(passage.satellite)
the `satellite` object within `session.merge` correctly has the `tle`
object, while the returned object from `session.merge` does not. Is there a
way to avoid that merge strips off the attributes that are not persisted in
the database?
it's not really "stripping" anything, it is locating an existing
"satellite" object and copying the attributes from the incoming object
onto it. So you would need to finish this copy operation and copy the
rest of the state that you care about.

If you'd prefer to discard the object that's already there so you can
just add() this one, then you can session.expunge(passage.satellite)
first.
Post by Ruben Di Battista
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper
http://www.sqlalchemy.org/
To post example code, please provide an MCVE: Minimal, Complete, and
Verifiable Example. See http://stackoverflow.com/help/mcve for a full
description.
---
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
--
SQLAlchemy -
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable Example. See http://stackoverflow.com/help/mcve for a full description.
---
You received this message because you are subscribed to the Google Groups "sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+***@googlegroups.com.
To post to this group, send email to ***@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
Continue reading on narkive:
Loading...