代码之家  ›  专栏  ›  技术社区  ›  Beau Simensen

如何在多个DDD存储库中有效地使用SQLAlchemy?

  •  3
  • Beau Simensen  · 技术社区  · 15 年前

    我一直在尝试找到一些如何使用sqlachemy实现存储库模式的示例。具体来说,实现多个存储库。

    在多个存储库的情况下,我相信每个存储库最好通过维护单独的SQLAlchemy会话来实现。但是,我在尝试将绑定到一个会话的对象实例移动到另一个会话时遇到了一个问题。

    首先,这样做有意义吗?每个存储库应该保持其自己的UOW独立于任何其他存储库,还是应该认为让整个上下文共享同一会话是安全的?

    第二,从一个会话分离实例并将其绑定到另一个会话的最佳方法是什么?

    第三,是否有任何用SQLAlchemy编写的可靠DDD存储库示例?

    1 回复  |  直到 15 年前
        1
  •  3
  •   Denis Otkidach    15 年前

    我不熟悉DDD存储库模式,但下面是一个示例,演示如何将对象从一个会话移动到另一个会话:

    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