Does Context/Scoping of a SQLAlchemy Session Require Non-Automatic Object/Attribute Expiration?
在我正在处理的应用程序中,特定类的实例在其生命周期结束时被持久化,虽然它们随后不会被修改,但可能需要读取它们的属性。例如,实例的
1 2 3 4 5 6 7 8 9 10 | class Foo(object): def __init__(self, position): self.start_time = time.time() self.end_time = None self.position = position # ... def finishFoo(self): self.end_time = time.time() self.duration = self.end_time - self.start_time # ... |
目标:使用 SQLAlchemy 持久化实例
遵循我认为的最佳实践 - 使用范围 SQLAlchemy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Database(object): # ... def scopedSession(self): session = self.sessionmaker() try: yield session session.commit() except: session.rollback() logger.warn("blah blah blah...") finally: session.close() # ... def saveMyFoo(self, foo): with self.scopedSession() as sql_session: sql_session.add(foo) logger.info("Foo number {0} finished at {1} has been saved." "".format(foo.position, foo.end_time)) ## Here the DetachedInstanceError is raised |
两种已知的可能解决方案:无到期或无范围
我知道我可以将
所以我的问题归结为:
1.
很可能,是的。就将数据正确保存到数据库而言,它的使用是正确的。但是,由于您的事务仅跨越更新,因此在更新同一行时可能会遇到竞争条件。根据应用程序,这可能没问题。
2.
不让属性过期是正确的做法。默认情况下到期的原因是因为它确保即使是幼稚的代码也能正常工作。如果你小心点,应该不会有问题。
3.
将事务的概念与会话的概念分开很重要。
提交后,您访问的任何后续属性都将导致启动新事务,以便 ORM 可以再次保证数据库中值的状态。
但是为什么会出现错误?这是因为您的会话已消失,因此 ORM 无法启动事务。如果您在上下文管理器块的中间执行
好吧,如果我只想访问先前获取的值怎么办?然后,您可以要求框架不要使这些属性过期。