Como uso efetivamente o SQLalChemy com vários repositórios DDD?
-
21-09-2019 - |
Pergunta
Eu tenho tentado encontrar alguns exemplos de como implementar o padrão de repositório com o SQLalChemy. Especificamente, implementando mais de um repositório.
No caso de vários repositórios, acredito que cada repositório seria melhor implementado, mantendo uma sessão separada de sqlalchemy. No entanto, tenho me dado um problema em tentar mover uma instância de um objeto ligado a uma sessão para outra sessão.
Primeiro, isso faz sentido fazer? Cada repositório deve manter seu próprio Uow separado de qualquer outro repositório ou deve ser considerado seguro ter todo o contexto compartilhar a mesma sessão?
Segundo, qual é a melhor maneira de destacar uma instância de uma sessão e vinculá -la a outra?
Terceiro, existem exemplos sólidos de repositório DDD escritos com sqlalchemy em mente?
Solução
Não sou familiar com o padrão de repositório DDD, mas abaixo está um exmaple mostrando como mover um objeto de uma sessão para outra:
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
metadata = MetaData()
Base = declarative_base(metadata=metadata, name='Base')
class Model(Base):
__tablename__ = 'models'
id = Column(Integer, primary_key=True)
engine1 = create_engine('sqlite://')
metadata.create_all(engine1)
engine2 = create_engine('sqlite://')
metadata.create_all(engine2)
session1 = sessionmaker(bind=engine1)()
session2 = sessionmaker(bind=engine2)()
# Setup an single object in the first repo.
obj = Model()
session1.add(obj)
session1.commit()
session1.expunge_all()
# Move object from the first repo to the second.
obj = session1.query(Model).first()
assert session2.query(Model).count()==0
session1.delete(obj)
# You have to flush before expunging, otherwise it won't be deleted.
session1.flush()
session1.expunge(obj)
obj = session2.merge(obj)
# An optimistic way to bind two transactions is flushing before commiting.
session2.flush()
session1.commit()
session2.commit()
assert session1.query(Model).count()==0
assert session2.query(Model).count()==1