显然use of ORM and Core in tandem is possible,但我无法找到对此策略的可靠解释。
这是用例类:
class DataHolder(Base):
__tablename__ = 'data_holder'
id = Column(Integer, primary_key=True)
dataset_id = Column(Integer, ForeignKey('data_set.id'))
name = Column(String)
_dataset_table = Table('data_set', Base.metadata,
Column('id', Integer, primary_key=True),
)
_datarows_table = Table('data_rows', Base.metadata,
Column('id', Integer, primary_key=True),
Column('dataset_id', None, ForeignKey('data_set.id')),
Column('row', Integer),
Column('col_0', Integer),
Column('col_1', Integer),
Column('col_2', Integer),
)
def __init__(self, name=None, data=None):
self.name = name
self.data = data
def _pack_info(self):
# Return __class__ and other info needed for packing.
def _unpack_info(self):
# Return info needed for unpacking.
name
应该通过the ORM保留。 data
应该是大型的NumPy数组(或类似类型),应通过the Core保留。
存在一个中间表'data_set'
,其目的是DataHolder
与数据之间的many-to-one关系。这允许数据集独立地存在于某些库中。 (此表的唯一目的是为新数据集生成ID。)
实际持久性将通过实现一些侦听器的类来实现,例如以下类。
class PersistenceManager:
def __init__(self):
self.init_db()
self.init_listeners()
def init_db(self):
engine = create_engine('sqlite:///path/to/database.db')
self.sa_engine = engine
self.sa_sessionmaker = sessionmaker(bind=engine)
Base.metadata.create_all(engine)
def init_listeners(self):
@event.listens_for(Session, 'transient_to_pending')
def pack_data(session, instance):
try:
pack_info = instance._pack_info()
# Use Core to execute INSERT for bulky data.
except AttributeError:
pass
@event.listens_for(Session, 'loaded_as_persistent')
def unpack_data(session, instance):
try:
unpack_info = instance._unpack_info()
# Use Core to execute SELECT for bulky data.
except AttributeError:
pass
def persist(self, obj):
session.add(obj)
def load(self, class_, spec):
obj = session.query(class_).filter_by(**spec).all()[-1]
return obj
def session_scope(self):
session = self.sa_sessionmaker()
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()
这个想法是,每当DataHolder
被保留时,其数据也将在相同(或几乎相同)的时间被保留。
监听'transient_to_pending'
(用于“打包”)和'loaded_as_persistent'
(用于“解包”)事件可以简化保存和加载。但是,似乎也应该注意监听'pending_to_transient'
事件。对于rollback,通过Core添加的数据不会以与ORM相关的数据相同的方式从数据库中拉回。
除了听'pending_to_transient'
之外,还有另一种更好的方法来操纵这种行为吗?在两个不同的DataHolder
引用同一数据集的情况下,这可能会引起问题:一个DataHolder
可以回滚,从数据库中删除该数据集,从而另一个DataHolder
不再使用它。