代码之家  ›  专栏  ›  技术社区  ›  funseiki

会话关闭后,读取DateTime列会出现DetachedInstanceError

  •  0
  • funseiki  · 技术社区  · 4 年前

    我想进入一个叫做 timeCreated utcnow() FunctionElement(取自此 example

    在做了一个 merge add 调用,提交,然后关闭会话,我注意到在访问字段时出现以下错误。我有 expire_on_commit 设置为False。

    sqlalchemy.orm.exc.DetachedInstanceError: Instance <User at 0x102046710> is not bound to a Session; attribute refresh operation cannot proceed (Background on this error at: http://sqlalche.me/e/13/bhk3)
    

    def write(obj):
        with sessionScope() as session:
            obj.timeCreated = utcnow()
            ret = session.merge(obj)
        return ret
    
    user = User(name='Totoro')
    savedUser = write(user)
    
    # Error occurs when accessing timeCreated
    print(savedUser.timeCreated)
    

    SessionScope()取自 these docs

    sessionFactory = sessionmaker(bind=engine)
    
    @contextmanager
    def sessionScope():
        try:
            session = sessionFactory()
            yield session
            session.commit()
        except Exception as e:
            session.rollback()
            raise
        finally:
            session.close()
        return
    

    timeCreated之后没有解析有什么原因吗 commit() ? 如果,在提交之后,但在关闭之前,我访问 ,然后在 close 还在工作。

    有没有办法“急切地”加载这种类型的列?

    0 回复  |  直到 4 年前
        1
  •  1
  •   snakecharmerb    4 年前

    问题是当 timeCreated 分配给调用的结果 utcnow ,SQLAlchemy不会立即从服务器分配结果;而是分配占位符值,如调试器中所示:

    (Pdb) obj.__dict__
    {..., 'timeCreated': <__main__.utcnow at 0x7f237d0a90a0; utcnow object>}
    

    (Pdb) sa.inspect(savedUser).expired_attributes
    {'timeCreated'}
    

    所以,正如在问题的最后所说 创建的时间 DetachedInstanceError 如果以后访问它。

    Fetching Server-Generated Defaults (case 1) 创建的时间 server_default 归属于 FetchedValue eager_defaults True 在映射器参数中。

    from sqlalchemy.schema import FetchedValue
    
    
    class User(Base):
        ...
        timeCreated = Column(DateTime, server_default=FetchedValue())
    
        __mapper_args__ = {'eager_defaults': True}
    

    server_default=utcnow() 与mapper args结合使用也同样有效,并且避免了设置 创建的时间 明确的;但也许OP有自己的理由这么做。