Prisma事务中传递DB对象至函数时出现事务已关闭错误
问题分析
报错Transaction already closed的核心原因是事务回调函数提前执行完毕,Prisma默认会在回调函数返回后立即关闭事务,而你的代码中有未被等待的异步操作,导致这些操作在事务关闭后才执行,从而触发错误。
具体问题点:
db.case_file.update调用后使用.then处理,但没有将这个Promise返回或等待,导致事务回调不等待更新完成就继续执行。createNotesAction是异步函数,但在.then回调中调用时没有使用await,这个异步操作完全脱离了事务的控制流。- 额外风险:
findOneByLeadId如果是直接使用this.prisma而非事务传入的db,该查询不在事务范围内,可能导致数据不一致。
解决方案
修正代码的异步控制流,确保所有事务内的异步操作都被正确等待,同时统一使用async/await风格:
createNote = async (input: CreateSupplementalNoteInput): Promise<CaseFile> => { const { leadIdentifier, notes, createUserId, actor } = input; const createNotesAction = async (db, caseId: string) => { const ACTION_CODE = "UPDATENOTE"; const ACTION_TYPE_CODE = "CASEACTION"; const xref = await db.action_type_action_xref.create({ data: { action_code: ACTION_CODE, action_type_code: ACTION_TYPE_CODE, create_user_id: createUserId, create_utc_timestamp: new Date(), }, }); await db.action.create({ data: { case_guid: caseId, action_type_action_xref_guid: xref.action_type_action_xref_guid, // 需传入xref的主键字段,原代码直接传对象会报错 actor_guid: actor, action_date: new Date(), create_user_id: createUserId, create_utc_timestamp: new Date(), }, }); }; try { const updatedCaseFile = await this.prisma.$transaction(async (db) => { // 改用事务内的db执行查询,确保查询在事务中 const caseFile = await db.case_file.findUnique({ where: { lead_identifier: leadIdentifier } // 替换原findOneByLeadId逻辑,使用事务db实例 }); if (!caseFile) { throw new Error("Case file not found"); } const { case_file_guid: caseIdentifier } = caseFile; // 等待更新操作完成 const updatedCase = await db.case_file.update({ where: { case_file_guid: caseIdentifier }, data: { note_text: notes, }, }); // 等待createNotesAction完成,确保事务不会提前关闭 await createNotesAction(db, caseIdentifier); return updatedCase; }); return updatedCaseFile; } catch (error) { console.log("exception: unable to create supplemental note", error); throw new GraphQLError("Exception occurred. See server log for details", {}); } };
关键注意事项
- 事务内必须等待所有异步操作:Prisma的
$transaction会在回调函数返回的Promise resolve后提交事务,如果有未等待的异步操作,事务会提前关闭。 - 统一使用async/await:避免混用
.then和await,减少异步控制流错误。 - 所有事务内操作使用传入的db实例:确保查询、更新、创建都在同一个事务中,避免数据不一致。
- 注意关联字段的正确传递:关联字段需要传入对应记录的主键值,而非整个对象。
内容的提问来源于stack exchange,提问作者Marqueone
相关产品推荐
相关产品推荐

