On Thu, Apr 3, 2014 at 4:44 PM, Joril <jor...@gmail.com> wrote:
> Hi everyone!
> I have a client-server application where sometimes I need to modify a
> cascaded member of a one-to-many relation directly, that is by saving itself
> instead of its parent. This works, but if later the user *does* save the
> parent, I get a "A conflicting state is already present in the identity map"
> error, and I don't know if I'm simply doing something I'm not supposed to :)
>
> I narrowed down the issue to this example:
>
>
> from sqlalchemy import Column, String, Integer, Table, ForeignKey
> from sqlalchemy.engine import create_engine
> from sqlalchemy.orm import sessionmaker, relationship
> from sqlalchemy.ext.declarative import declarative_base
>
> Base = declarative_base()
>
> class Child(Base):
>    __tablename__ = "children"
>
>    id = Column(Integer, primary_key=True)
>    parent_id = Column(Integer, ForeignKey("parents.id"))
>
> class Parent(Base):
>    __tablename__ = "parents"
>
>    id = Column(Integer, primary_key=True)
>    children = relationship(Child, cascade="save-update", uselist=True)
>
> en = create_engine("sqlite:///:memory:", echo=True)
> Base.metadata.create_all(en)
> maker = sessionmaker(en)
> session = maker(autocommit=True)
>
> # Save a parent with a child
> par = Parent()
> par.children = [ Child() ]
> session.add(par)
> session.flush()
>
> child_id = par.children[0].id # For later
>
> # Clean the session (simulate another client-server session)
> session.expunge_all()
>
> # Reload the children
> q = session.query(Child)
> q = q.filter(Child.id == child_id)
> child_reloaded = q.first()
>
> # Reassign to the parent and save
> par.children = [child_reloaded]
> session.add(par)
>
>
> I tested this on SQLalchemy 0.9.4:
>
> Traceback (most recent call last):
>   File "testsa.py", line 44, in <module>
>     session.add(par)
>   File "/home/joril/src/newprg/branches/sqla09/sqlalchemy/orm/session.py",
> line 1478, in add
>     self._save_or_update_state(state)
>   File "/home/joril/src/newprg/branches/sqla09/sqlalchemy/orm/session.py",
> line 1497, in _save_or_update_state
>     self._save_or_update_impl(st_)
>   File "/home/joril/src/newprg/branches/sqla09/sqlalchemy/orm/session.py",
> line 1746, in _save_or_update_impl
>     self._update_impl(state)
>   File "/home/joril/src/newprg/branches/sqla09/sqlalchemy/orm/session.py",
> line 1739, in _update_impl
>     self.identity_map.add(state)
>   File "/home/joril/src/newprg/branches/sqla09/sqlalchemy/orm/identity.py",
> line 119, in add
>     % (key, ))
> AssertionError: A conflicting state is already present in the identity map
> for key (<class '__main__.Child'>, (1,))
>
> Is this supposed to happen?
>
> Many thanks!
>

I'm not sure if this is the reason for your error, but I don't think
I'd expect your example to work because you are attaching the freshly
loaded child instance to a parent which is no longer associated with a
session. What happens in your test if you reload the parent instance
first?

Simon

-- 
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+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to