我在 FastAPI 项目中使用 SQLAlchemy 时遇到问题。我已经设置了一条路线,该路线应该使用上下文管理器和嵌套事务将项目添加到数据库中。如果单个项目未能添加(由于限制或任何原因),则不应将其包含在提交中。但是,应包括之前或之后添加的其余项目。
使用嵌套事务时,我希望能够跟踪失败和成功的添加。但是,我不断遇到以下错误:
sqlalchemy.exc.InvalidRequestError: Can't operate on a closed transaction inside a context manager.
我在下面提供了相关代码:
router = APIRouter()
def get_session() -> Generator[Session, None, None]:
cached_sessionmaker = get_session_maker()
with cached_sessionmaker.begin() as session:
yield session
@router.post("/items")
def add_items(
session: Session = Depends(get_database.get_session),
) -> Dict[str, Any]:
request_inputs = [
RequestInput(name="chair", used_for="sitting"),
RequestInput(name="table", used_for="dining"),
RequestInput(name="tv", used_for="watching"),
]
uploaded_items = []
failed_items = []
for request_input in request_inputs:
try:
with session.begin_nested():
item= Item(
**request_input.dict()
)
session.add(item)
session.refresh(item)
uploaded_items += 1
except IntegrityError as e:
# Handle any integrity constraint violations here
session.rollback()
failed_items += 1
except Exception as e:
# Handle other exceptions
session.rollback()
failed_items += 1
session.commit()
return {
"uploaded": uploaded_items,
"failed": failed_items,
}
这显然是由于我的会话过早关闭造成的,但是我无法弄清楚在哪里提前关闭事务,同时尝试将所有未失败的项目添加到我的数据库中。有人可以帮助我理解为什么会遇到此错误以及如何修复它吗?
预先感谢您的协助。
我尝试使用 session.begin_nested() 来跟踪我的事务的状态,但是它似乎在某个地方关闭了。如果不使用 begin_nested(),我只提交失败实例之前的项目。之后的所有项目均被排除。
该错误是由
except
块内的回滚引起的。他们回滚outer事务,使外部上下文管理器无法使用。
begin_nested()
创建的内层事务如果发生异常会自动回滚,所以不需要回滚外层事务。