postgresql - 创建记录并将其连接到现有记录 prisma 客户端(1 对 1 关系)

标签 postgresql next.js prisma next-auth

我正在使用 prisma 和 postgres 制作 Next JS 应用程序。
我有 2 个表:用户个人资料
他们的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 本身会将用户的记录添加到用户表中。 到这里为止,没有任何问题。

然后,当用户第一次打开仪表板时,他会看到一个需要填写的表单,提交该表单后,需要在配置文件表中插入一条记录。由于配置文件和用户表是链接的,因此它们也需要连接。

因此,当用户提交个人资料详细信息表单时,我会这样做:

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 关系创建记录的正确方法吗?

最佳答案

修复:

我认为您需要从个人资料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});

解释:

个人资料useruserId字段don't directly translate to actual columns on the db但是是让 Prisma 处理关系之间的链接的字段。它最终被翻译成 PostgreSQL 的

create table profile(
    --...
    userId text references user (id),
    --...
);

稍后,当您发出 user:{connect:{id:'1'}} 时,Prisma 会使用您的用户id 填充该字段。可能发生的情况是,当您在 userId 字段定义中使用 @default(cuid()) 时,您干扰了该过程。现在该列最终为

    userId text default gen_random_uuid() references user (id)

每当您创建个人资料时,都会输入一个新行,而无需指定您自己的userId(Prisma 可能会在尝试链接您的< strong>User),生成的随机 ID 与任何现有的 User 都不对应,这违反了引用约束。

就是这样和/或您对 include: { user: true } 的使用弄乱了一些东西,产生了一个单独的新用户,即使您尝试链接您的个人资料到现有的。但我希望这只是一个不需要的副作用,使您的代码在每次创建 Profile 时生成无用的 User 对象和行。

一旦摆脱了@default(cuid()),您还可以生成一个独立的、未链接的配置文件,然后将其链接到适当的用户稍后使用更新声明。

关于postgresql - 创建记录并将其连接到现有记录 prisma 客户端(1 对 1 关系),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70197070/

相关文章:

typescript - 将 Object<T> 转换为 Object<A>,其中 A 包含在 T 中

sql - 删除前Postgres触发器检查数量

reactjs - next js Image 100%宽度和比例高度

postgresql - 返回错误号

reactjs - 构建并部署后,Tailwind css 无法在 Vercel 上运行

javascript - 在 useState 使用 react 时出现错误 "TypeError: Cannot read properties of null (reading ' useState')"

postgresql - Prisma 与 Bit.io 连接问题

mysql - 棱镜数据模型 : Primary key as a combination of two relational models

python - psycopg2 共享内存不足并提示增加 max_pred_locks_per_transaction

sql - SQL中的候选匹配