Prisma嵌套写入创建关联记录抛出unknown args参数错误
问题说明
使用的精简Prisma Schema定义如下:
model PATIENT { patient_id Int @id @default(autoincrement()) patient_name String patient_identity_card BigInt @unique password String wallet_id Int? birthday DateTime address String status_id Int gender String @default("Nam") phone String @default("0935438280") current_treatment_place_id Int avatar_url String? treatment_place TREATMENT_PLACE @relation(fields: [current_treatment_place_id], references: [place_id]) status PATIENT_STATUS @relation(fields: [status_id], references: [status_id]) card CART? patient_passive_contact PATIENT_CONTACT[] @relation("ActiveContact_referredToPatient") patient_active_contact PATIENT_CONTACT[] @relation("PassiveContact_referredToPatient") BE_MANAGED_HISTORY BE_MANAGED_HISTORY[] } model BE_MANAGED_HISTORY { place_id Int patient_id Int time DateTime status_id Int status PATIENT_STATUS @relation(fields: [status_id], references: [status_id]) patient PATIENT @relation(fields: [patient_id], references: [patient_id]) place TREATMENT_PLACE @relation(fields: [place_id], references: [place_id]) change_type_id Int change_type CHANGE_MANAGED_HISTORY_TYPE @relation(fields: [change_type_id], references: [type_id]) @@id([place_id, patient_id, time]) }
业务需求为创建一条BE_MANAGED_HISTORY记录,同时通过嵌套写入同步创建关联的PATIENT记录,初始实现代码如下:
const res = await prisma.BE_MANAGED_HISTORY.create({ data: { place_id: treatmentPlaceId, time: new Date(startDate), status_id: patientStatus, change_type_id: 1, patient: { create: { patient_name: patientName, gender, birthday: new Date(birthday), patient_identity_card: identity, password: hashedPassword, phone, address, status_id: patientStatus, current_treatment_place_id: treatmentPlaceId, avatar_url: avatarUrl, } } }, })
执行代码时Prisma抛出错误:
Unknown arg
patientin data.patient for type BE_MANAGED_HISTORYUncheckedCreateInput. Did you meanpatient_id?
Argument patient_id for data.patient_id is missing.
问题解答
- 首先明确:完全支持在创建BE_MANAGED_HISTORY记录时通过嵌套写入同步创建关联的PATIENT记录,报错和功能支持无关,是写法触发了Prisma的输入类型校验规则导致的。
- 报错根因:Prisma的create操作有两类输入类型:
UncheckedCreateInput:当你在data中直接写入外键字段值(比如代码里的place_id、status_id、change_type_id)时,Prisma会自动使用这个类型校验,该类型仅接受外键的纯值传入,不支持关系字段的嵌套写入语法,因此无法识别patient这个关系字段,同时要求必须传入必填外键patient_id的值。- 普通
CreateInput:也就是支持嵌套写入的校验类型,该类型下不接受直接传入外键值,需要通过关系字段的connect(关联已存在记录)、create(嵌套新建关联记录)操作来处理关联关系。
- 修复方法:将所有直接传入外键值的写法改为通过关系字段
connect关联已存在记录,让Prisma走支持嵌套写入的CreateInput校验逻辑即可,修复后的代码如下:
const res = await prisma.BE_MANAGED_HISTORY.create({ data: { time: new Date(startDate), // 关联已存在的治疗地点 place: { connect: { place_id: treatmentPlaceId } }, // 关联已存在的患者状态 status: { connect: { status_id: patientStatus } }, // 关联已存在的变更类型 change_type: { connect: { type_id: 1 } }, // 嵌套创建关联的患者记录 patient: { create: { patient_name: patientName, gender, birthday: new Date(birthday), patient_identity_card: identity, password: hashedPassword, phone, address, status_id: patientStatus, current_treatment_place_id: treatmentPlaceId, avatar_url: avatarUrl, } } }, })
- 补充说明:上述写法会自动在Prisma的内置事务中执行,先创建PATIENT记录拿到自增的
patient_id,再联合其他关联的外键值创建BE_MANAGED_HISTORY记录,不会出现单条记录写入成功的脏数据问题,满足业务一致性要求。
内容的提问来源于stack exchange,提问作者Hung Vo
相关产品推荐
相关产品推荐

