如何有效地将SQLAlchemy用于多个DDD存储库?

时间:2010-02-16 21:33:15

标签: domain-driven-design sqlalchemy ddd-repositories

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

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

首先,这样做有意义吗?每个存储库是否应该将自己的UoW与任何其他存储库分开维护,还是应该认为整个上下文共享同一个会话是安全的?

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

第三,有没有用SQLAlchemy编写的可靠的DDD存储库示例?

1 个答案:

答案 0 :(得分:3)

我不熟悉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