创建记录并将其连接到现有记录 prisma 客户端(1 对 1 关系)
Create a record and connect it to an existing record prisma client (1 to 1 relation)
我正在使用 prisma 和 postgres 制作 Next JS 应用程序。
我有 2 个 table:User 和 Profile
它们的 prisma schema 结构如下:
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
// foreign keys
sessions Session[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
isAdmin Boolean @default(false)
firstName String
lastName String
email String @unique
phone String
address String
gender String
image Bytes
guardianName1 String
guardianPhone1 String
guardianRelation1 String
guardianName2 String?
guardianPhone2 String?
guardianRelation2 String?
guardianName3 String?
guardianPhone3 String?
guardianRelation3 String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// foreign keys
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @default(cuid()) // relation scalar field (used in the `@relation` attribute above)
requests Request[]
}
我还使用 next-auth
作为此应用程序的身份验证部分。因此,当用户注册并通过电子邮件验证时,next-auth 本身会将用户的记录添加到用户 table。
到这里,没有问题。
然后,当用户第一次打开他的仪表板时,他会看到一个要填写的表格,提交该表格后,需要在配置文件中插入一条记录 table。由于配置文件和用户 table 已关联,因此它们也需要关联。
所以当用户提交个人资料详细信息表单时,我这样做:
try {
const newProfileData = {
// other fields data here...
user: {
connect: { id: '1' } // where User table already has a record with - 'id': 1
}
};
const profile = await prisma.profile.create({ data: newProfileData, include: { user: true } });
if(profile) {
console.log("Created: ", profile);
res.status(200).json({ msg: 'Successfully Created Profile!' });
}
}
catch(err)
{
console.log(err);
}
但是在 运行 这段代码中,我得到了错误:
The change you are trying to make would violate the required relation 'ProfileToUser' between the `Profile` and `User` models.
...
code: 'P2014',
clientVersion: '2.30.3',
meta: {
relation_name: 'ProfileToUser',
model_a_name: 'Profile',
model_b_name: 'User'
}
如何解决?
我什至尝试了另一种方式(即更新现有用户并创建与其连接的配置文件记录):
const user = await prisma.user.update({
where: {
email: req.body.email,
},
data: {
profile: {
create: {
// data fields here... (without the user field)
},
},
},
});
但这也给出了同样的错误...
我想了解为什么会出现错误。这不是使用 prisma-client 为 1 对 1 关系创建记录的正确方法吗?
将两个表合并为一个,类似于:
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
isAdmin Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// foreign keys
sessions Session[]
}
如果您绝对必须有个人资料关系,请创建数据库视图:
create view Profile as
select
id,
isAdmin,
name,
email,
createdAt,
updatedAt,
userId
from user
并将其映射为只读关系,但我看不出重点。
修复:
我认为您需要从 个人资料 的 userId
字段定义中删除 @default(cuid())
。
model Profile {
//...
// foreign keys
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String // relation scalar field (used in the `@relation` attribute above)
//...
}
同时去掉 include: { user: true }
:
const profile = await prisma.profile.create({ data: newProfileData});
解释:
Profile 的 user
和 userId
字段 don't directly translate to actual columns on the db 但是是让 Prisma 处理 link 之间的字段关系。它最终被翻译成 PostgreSQL 的
create table profile(
--...
userId text references user (id),
--...
);
稍后,当您发出 user:{connect:{id:'1'}}
时,Prisma 将使用您的 User 的 id
填充该字段。可能发生的情况是,当您在 userId
字段定义中使用 @default(cuid())
时,您干扰了该过程。现在该列结束为
userId text default gen_random_uuid() references user (id)
并且每当您创建 Profile 时,都会输入一个新行,而无需指定您自己的 userId
(Prisma 可能会尝试这样做,然后才会尝试 link your User), 生成一个随机 ID,它不对应于任何现有的 User,这违反了引用约束。
就是 and/or 你对 include: { user: true }
的使用搞砸了产生一个单独的新用户,即使你试图 link 你的 个人资料 到现有的。但我希望这只是一个不需要的副作用,使您的代码在每次创建 Profile 时生成一个无用的 User 对象和行。
一旦你摆脱了 @default(cuid())
你也可以生成一个独立的,unlinked Profile 然后 link 它稍后使用更新语句发送给适当的 User。
我正在使用 prisma 和 postgres 制作 Next JS 应用程序。
我有 2 个 table:User 和 Profile
它们的 prisma schema 结构如下:
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
// foreign keys
sessions Session[]
profile Profile?
}
model Profile {
id Int @id @default(autoincrement())
isAdmin Boolean @default(false)
firstName String
lastName String
email String @unique
phone String
address String
gender String
image Bytes
guardianName1 String
guardianPhone1 String
guardianRelation1 String
guardianName2 String?
guardianPhone2 String?
guardianRelation2 String?
guardianName3 String?
guardianPhone3 String?
guardianRelation3 String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// foreign keys
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @default(cuid()) // relation scalar field (used in the `@relation` attribute above)
requests Request[]
}
我还使用 next-auth
作为此应用程序的身份验证部分。因此,当用户注册并通过电子邮件验证时,next-auth 本身会将用户的记录添加到用户 table。
到这里,没有问题。
然后,当用户第一次打开他的仪表板时,他会看到一个要填写的表格,提交该表格后,需要在配置文件中插入一条记录 table。由于配置文件和用户 table 已关联,因此它们也需要关联。
所以当用户提交个人资料详细信息表单时,我这样做:
try {
const newProfileData = {
// other fields data here...
user: {
connect: { id: '1' } // where User table already has a record with - 'id': 1
}
};
const profile = await prisma.profile.create({ data: newProfileData, include: { user: true } });
if(profile) {
console.log("Created: ", profile);
res.status(200).json({ msg: 'Successfully Created Profile!' });
}
}
catch(err)
{
console.log(err);
}
但是在 运行 这段代码中,我得到了错误:
The change you are trying to make would violate the required relation 'ProfileToUser' between the `Profile` and `User` models.
...
code: 'P2014',
clientVersion: '2.30.3',
meta: {
relation_name: 'ProfileToUser',
model_a_name: 'Profile',
model_b_name: 'User'
}
如何解决? 我什至尝试了另一种方式(即更新现有用户并创建与其连接的配置文件记录):
const user = await prisma.user.update({
where: {
email: req.body.email,
},
data: {
profile: {
create: {
// data fields here... (without the user field)
},
},
},
});
但这也给出了同样的错误...
我想了解为什么会出现错误。这不是使用 prisma-client 为 1 对 1 关系创建记录的正确方法吗?
将两个表合并为一个,类似于:
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
isAdmin Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
// foreign keys
sessions Session[]
}
如果您绝对必须有个人资料关系,请创建数据库视图:
create view Profile as
select
id,
isAdmin,
name,
email,
createdAt,
updatedAt,
userId
from user
并将其映射为只读关系,但我看不出重点。
修复:
我认为您需要从 个人资料 的 userId
字段定义中删除 @default(cuid())
。
model Profile {
//...
// foreign keys
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String // relation scalar field (used in the `@relation` attribute above)
//...
}
同时去掉 include: { user: true }
:
const profile = await prisma.profile.create({ data: newProfileData});
解释:
Profile 的 user
和 userId
字段 don't directly translate to actual columns on the db 但是是让 Prisma 处理 link 之间的字段关系。它最终被翻译成 PostgreSQL 的
create table profile(
--...
userId text references user (id),
--...
);
稍后,当您发出 user:{connect:{id:'1'}}
时,Prisma 将使用您的 User 的 id
填充该字段。可能发生的情况是,当您在 userId
字段定义中使用 @default(cuid())
时,您干扰了该过程。现在该列结束为
userId text default gen_random_uuid() references user (id)
并且每当您创建 Profile 时,都会输入一个新行,而无需指定您自己的 userId
(Prisma 可能会尝试这样做,然后才会尝试 link your User), 生成一个随机 ID,它不对应于任何现有的 User,这违反了引用约束。
就是 and/or 你对 include: { user: true }
的使用搞砸了产生一个单独的新用户,即使你试图 link 你的 个人资料 到现有的。但我希望这只是一个不需要的副作用,使您的代码在每次创建 Profile 时生成一个无用的 User 对象和行。
一旦你摆脱了 @default(cuid())
你也可以生成一个独立的,unlinked Profile 然后 link 它稍后使用更新语句发送给适当的 User。