欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DetachedInstanceError:Instance is not bound to a Session; attribute refresh operation cannot proced

程序员文章站 2024-03-02 21:59:34
...

有同事使用SQLAlchemy 遇到类似下边这样的报错:

DetachedInstanceError: Instance <User at 0x32768d0> is not bound to a Session; attribute refresh operation cannot proceed

搜索了下找到了答案,这种情况主要是发生在 关闭数据库会话后,使用ORM的对用,获取对象的某些字段值,这时就会报错。

报错的原因也很简单,SQLAlchemy的ORM方式将数据库中的记录映射成了我们定义好的模型类,这些类对象的实例只在数据库会话(session)的生命期内有效,假如我们将数据库会话关闭了,再访问数据表类的对象就会报错。类似代码如下:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()


class User(Base):
    __tablename__ = 'USER'

    id = Column(Integer, Sequence('USER_SEQ'), primary_key=True, autoincrement=True)
    name = Column(String(30))
    age = Column(Integer)
    status = Column(String(30))


engine = create_engine(str(db_url), encoding=b'utf-8', echo=echo, convert_unicode=True)
Session = sessionmaker(bind=engine)
session = Session()

user = User(name='John', age=30)
session.add(user)
session.commit()
session.close()

print user.name

运行到最后一行会抛出异常:

Traceback (most recent call last):
  File "E:\WorkCopy\test\test.py", line 21, in test_something
    print user.name
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\attributes.py", line 237, in __get__
    return self.impl.get(instance_state(instance), dict_)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\attributes.py", line 573, in get
    value = state._load_expired(state, passive)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\state.py", line 480, in _load_expired
    self.manager.deferred_scalar_loader(self, toload)
  File "C:\Python27\lib\site-packages\sqlalchemy\orm\loading.py", line 610, in load_scalar_attributes
    (state_str(state)))
DetachedInstanceError: Instance <User at 0x32768d0> is not bound to a Session; attribute refresh operation cannot proceed

 那么如何在关闭Session 后还可以正常使用这个对象呢? 使用 session.expunge()。

user = User(name='John', age=30)
session.add(user)
session.commit()

session.refresh(user)
session.expunge(user)

session.close()

print user.name

使用 session.refresh(user) 是为了读取自增字段值(如果有的话)到 user 对象

 

问题参考链接:

https://segmentfault.com/q/1010000004530775

相关标签: SQLAlchemy