Cree un registro y conéctelo a un registro existente de cliente prisma (relación 1 a 1).
Estoy haciendo una aplicación de Next JS con Prisma y Postgres. Tengo 2 tablas: Usuario y Perfil. Su estructura de esquema Prisma es la siguiente:
modelo Usuario {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime?
image String?
// claves foráneas
sessions Session[]
profile Profile?
}
modelo 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
// claves foráneas
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String @default(cuid()) // campo escalar de relación (usado en el atributo <code>@relation</code> anterior)
requests Request[]
}
También estoy usando next-auth
para la autenticación de esta aplicación. Así que cuando un usuario se registra, después de la verificación de su correo electrónico, next-auth agrega automáticamente el registro del usuario a la tabla Usuario. Hasta aquí, no hay problema.
Luego, cuando el usuario abre su panel por primera vez, se le muestra un formulario para completar. Al enviar ese formulario, se necesita insertar un registro en la tabla Perfil. Como las tablas Perfil y Usuario están relacionadas, también necesitan estar conectadas.
Así que cuando el usuario envía el formulario de detalles del perfil, hago lo siguiente:
try {
const newProfileData = {
// otros datos de los campos aquí...
user: {
connect: { id: '1' } // donde la tabla Usuario ya tiene un registro con - 'id': 1
}
};
const profile = await prisma.profile.create({ data: newProfileData, include: { user: true } });
if(profile) {
console.log("Creado: ", profile);
res.status(200).json({ msg: 'Perfil creado correctamente!' });
}
}
catch(err)
{
console.log(err);
}
Pero al ejecutar este código, obtengo el error:
El cambio que estás intentando hacer violaría la relación requerida 'PerfilAUsuario' entre los modelos `Perfil` y `Usuario`.
...
codigo: 'P2014',
clientVersion: '2.30.3',
meta: {
relation_name: 'ProfileToUser',
model_a_name: 'Profile',
model_b_name: 'User'
}
¿Cómo se puede solucionar esto? Incluso lo intenté de otra manera (es decir, actualizando el Usuario existente y creando el registro del Perfil conectado a él):
const user = await prisma.user.update({
where: {
email: req.body.email,
},
data: {
profile: {
create: {
// datos de los campos aquí... (sin el campo user)
},
},
},
});
Pero esto también da el mismo error… Quiero entender por qué viene el error. ¿No es esta la forma correcta de crear un registro para una relación 1 a 1 usando Prisma Client?
davy.ai
El mensaje de error sugiere que la relación entre los modelos
Profile
yUser
no se cumple al intentar crear un nuevo registro en la tablaProfile
. Esto se debe a que cada registro deProfile
debe estar vinculado a un registro correspondiente deUser
mediante el campouserId
, que actúa como una clave externa.Para solucionar esto, debes asegurarte de que el campo
userId
en el objetonewProfileData
esté configurado con el mismo valorid
que el registro deUser
al que deseas vincularlo. En lugar de codificar el valorid
como'1'
, puedes obtenerlo dinámicamente del objeto de usuario autenticado proporcionado pornext-auth
cuando el usuario inicia sesión.Suponiendo que hayas agregado un callback de sesión a
next-auth
para recuperar los datos del usuario de Prisma, puedes acceder al valorid
del usuario actual utilizandosession.user.id
. Aquí hay un ejemplo de cómo puedes actualizar tu código para configurar dinámicamente el campouserId
:Al configurar el campo
userId
con el valorid
del usuario actualmente conectado, estás asegurando que los registros deProfile
yUser
estén correctamente vinculados, y el mensaje de error ya no debería aparecer.