the order in which you put things into session.add() is significant only
within the scope of a certain mapped class, that is, the order that you put
a bunch of Foo() objects into session.add() will be maintained, however a
series of Bar() objects are handled separately.
Between different object hierarchies, the unit of work only takes into
account those dependencies established between hierarchies, which is most
commonly via relationship(). That is, if you have a series of Foo objects
which have one-to-many associations to a series of Bar objects, even if you
session.add() the Bar objects first, the unit of work can’t INSERT the Bar
objects first, as they are dependent on the Foo objects being present.
If there is no particular dependency between two classes, that is no
relationship(), then there’s no determinism to when the series of Foo or Bar
objects are inserted, they will be inserted in add() order only within the
scope of Foo and Bar. An exception to this occurs if there are
self-referential relationships involved, say if a Foo has a collection of
Foo objects related to it, or even a subclass, such as Foo->SubFoo(Foo);
in that case, the order within Foo objects themselves needs to be based
on foreign key dependency first.
The aspect of dependencies between mappers is normally established by the
fact of a relatlonship() establishing a partial ordering between those two
mappers. However, there is semi-public API that may be used to add
additional dependencies between mappers at flush time. If you really can’t
add any kind of relationship() between the mappers in question, an approach
like the one below may be used, though this is only semi-public API. There
should ideally be some public way to add dependencies like this between
mappers.
from sqlalchemy import Column, create_engine, Integer
from sqlalchemy.orm import Session, unitofwork
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import event
from sqlalchemy import inspect
Base = declarative_base()
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
class B(Base):
__tablename__ = 'b'
id = Column(Integer, primary_key=True)
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
@event.listens_for(Session, "before_flush")
def set_b_dependent_on_a(session, flush_context, objects):
b_mapper = inspect(B)
a_mapper = inspect(A)
save_bs = unitofwork.SaveUpdateAll(flush_context, b_mapper)
save_as = unitofwork.SaveUpdateAll(flush_context, a_mapper)
flush_context.dependencies.add((save_as, save_bs))
s = Session(e)
s.add_all([A(), A(), B(), A(), B()])
s.commit()
Victor Poluksht <[email protected]> wrote:
> I've found that sometimes sqlalchemy inserts objects during session.commit()
> not in the order they have been added using session.add()
>
> I've put my code example and the output to the github gist.
>
> https://gist.github.com/vpol/8da4a512308ae351eaf6
>
> My question is similar to this one:
> http://stackoverflow.com/questions/10154343/is-sqlalchemy-saves-order-in-adding-objects-to-session
>
> Is it possible to make sqlalchemy guarantee the order of insert.
>
> --
> 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 [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.
--
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.