异步SQLAlchemy提交后访问查询结果报错问题咨询
异步SQLAlchemy提交会话后访问实例属性报错的原因
核心原因:异步Session提交后实例会被脱管
异步SQLAlchemy的Session执行await session.commit()后,会立即将所有托管的模型实例从会话中移除(进入脱管状态)。此时实例不再与活跃会话关联,若访问的属性属于延迟加载(比如未提前读取的字段、关系属性),就会因为没有会话支持查询而抛出DetachedInstanceError类错误。
而同步SQLAlchemy的Session默认在提交后不会立即脱管实例,实例仍与会话保持关联,所以能正常触发延迟加载或访问属性,这就是同步与异步版本的关键差异。
你的代码报错的具体原因
你在提交会话后才读取user.id、user.username等属性:
return JSONResponse( content = { "user": { "id": user.id, "username": user.username, "age": user.age } }, status_code = 200 )
此时user已经是脱管实例,若这些属性中有延迟加载的字段(哪怕是普通字段,若SQLAlchemy默认延迟加载机制未提前读取),访问时就会触发报错。而之前仅返回字符串的代码未访问这些属性,因此不会出现问题。
可行的解决办法
提交前提前读取所有需要的属性:
在await session.commit()之前,先把需要的属性值提取到字典中,提交后直接用该字典构造响应:async def createUser() -> JSONResponse: async with Session() as session: userRawQuery = await session.execute( select(User).filter(User.id == 'some-value') ) user = userRawQuery.scalar() user.username = 'John' # 提前读取所有需要的属性 user_data = { "id": user.id, "username": user.username, "age": user.age } await session.commit() return JSONResponse( content = {"user": user_data}, status_code = 200 )修改Session配置,关闭提交后自动过期:
初始化Session时设置expire_on_commit=False,提交后实例不会被脱管,但要注意异步环境下可能存在的并发风险(比如实例状态与数据库不一致):from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession from sqlalchemy.orm import sessionmaker engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db") AsyncSessionLocal = sessionmaker( engine, class_=AsyncSession, expire_on_commit=False )
内容的提问来源于stack exchange,提问作者ILIKETOLEARN
相关产品推荐
相关产品推荐

