因此,我正在构建一个 Next TS 项目,并且我制作了一个表单,当用户填写该表单时,单击提交按钮会将其数据发送到我的 Azure SQL 数据库。我正在使用 Prisma ORM 将我的代码与数据库集成。我已经启动了 Prisma 并构建了 API 路线。
这是我的API路线:
import { PrismaClient } from "@prisma/client";
import { NextApiRequest, NextApiResponse } from "next";
import { z } from "zod";
const prisma = new PrismaClient();
const bigIntSchema = z.union([
z.string().regex(/^\d+$/).transform(val => BigInt(val)),
z.number().int().transform(val => BigInt(val))
]);
const ownerSchema = z.object({
fullName: z.string().min(1, "Full name is required"),
phoneNo: z.string().regex(/^[\d\s-+()]*$/, "Invalid phone number format"),
gymName: z.string().min(1, "Gym name is required"),
gymAddress: z.string().min(1, "Gym address is required"),
images: z.string(),
subscriptionPackages: z.string(),
gymContactInfo: z.string(),
workoutsOffered: z.string().optional(),
equipmentsAvailable: z.string().optional(),
ledger_start_transaction_id: bigIntSchema,
ledger_start_sequence_number: bigIntSchema
});
export async function POST(req: NextApiRequest, res: NextApiResponse) {
const parsedBody = ownerSchema.safeParse(req.body);
if (!parsedBody.success) {
return res.status(400).json({ message: "Invalid input", errors: parsedBody.error.flatten() });
}
try {
const newGymOwner = await prisma.gymOwners.create({
data: parsedBody.data
});
return res.status(201).json({ message: 'Gym owner created successfully', data: newGymOwner });
} catch (error) {
console.error('Error creating gym owner:', error);
return res.status(500).json({ message: "Could not create gym owner", error: error instanceof Error ? error.message : 'Unknown error' });
} finally {
await prisma.$disconnect();
}
}
但是每当我在 Postman 上测试它时,它都会显示 500:内部服务器错误。
这也是我的表单组件的一部分:
import AnotherButton from "@/components/buttons/AnotherButton"
import PrimaryButton from "@/components/buttons/PrimaryButton"
import axios from "axios"
import { log } from "console"
import { useState } from "react"
export default function GymOwners() {
const style = {
"border": "1px solid black"
}
const [formData, setFormData] = useState({
fullName: '',
phoneNumber: '',
gymName: '',
gymAddress: '',
images: '',
subscriptionPackages: '',
gymContactInfo: '',
workoutsOffered: '',
equipmentsAvailable: '',
})
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
const res = await axios.post("http://localhost3000/api/v1/gymowners", formData);
console.log(res.status)
} catch(e: any) {
console.log("Error:", e);
}
}
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
setFormData({
...formData,
[e.target.name]: e.target.value
})
}
return (
<div className="flex justify-center min-h-screen bg-gray-100">
<div className="flex flex-col w-full max-w-3xl border border-gray-300 bg-white rounded-lg shadow-lg p-8 pt-16">
<h2 className="text-3xl font-bold text-center text-gray-800 mb-8">
Create Gym Owner
</h2>
<form className="space-y-6">
<div>
<label className="block text-lg font-medium text-gray-700">
Full Name:
<input
className="w-full mt-2 p-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
onChange={handleChange}
type="text"
name="fullName"
required
/>
P.S:我正在使用 Next TS 14
我尝试了您的代码,并在更新示例数据后遇到了内部服务器错误。此问题可能是由于防火墙设置和
prisma/schema.prisma
中使用的数据类型(例如 @unique
和 String?
)造成的。在您的代码中,我注意到与数据库的连接设置:
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
await prisma.$connect();
console.log("Successfully connected to the database.");
添加以下代码以记录连接到 Azure SQl 服务器时的错误:
catch (error) {
// Log the error details
console.error('Error connecting to the database:', error);
}
添加此代码用于处理添加数据后的数据错误,使用此代码处理
P2002
错误和其他与数据相关的问题:
res.status(200).json({ message: "User created successfully", user });
} catch (error) {
console.error("Error creating user:", error);
将 Azure SQL 数据库连接到 Next.js TypeScript 的步骤:
请参阅此链接,使用 Next.js 和 Prisma 构建全栈应用程序。 请参阅本指南在 Prisma 中使用 Microsoft SQL Server 并在 Prisma 中设置影子数据库。
使用以下命令创建 Next.js 项目后:
npx create-next-app --example https://github.com/prisma/blogr-nextjs-prisma/tree/main blogr-nextjs-prisma
安装 Prisma CLI 和客户端:
npm install @prisma/client
npm install prisma --save-dev
在您的项目中初始化 Prisma。 此命令创建一个
prisma
文件夹,其中包含 schema.prisma
文件和 .env
文件:
npx prisma init
更新您的
schema.prisma
文件以包含 SQL Server 的配置:
datasource db {
provider = "sqlserver"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model User {
//Your SQl Filed name and filed type details
}
将数据库连接字符串添加到
.env
文件中:
DATABASE_URL="sqlserver://AzureSQlServerName.database.windows.net:1433;database=MainDatabaseName;user=UserName;password=YourPassword;encrypt=true;trustServerCertificate=false;connectionTimeout=30"
SHADOW_DATABASE_URL="sqlserver://AzureSQlServerName.database.windows.net:1433;database=ShadowDatabaseName;user=UserName;password=YourPassword;encrypt=true;trustServerCertificate=false;connectionTimeout=30"
运行以下命令来创建初始迁移:
npx prisma migrate dev --name init
生成 Prisma 客户端以与数据库交互:
npx prisma generate
pages/api/submit.ts
。components/UserForm.tsx
。UserForm
和类 pages/index.tsx
来调用 div
文件中的 form-container
组件。您可以使用
headers
中的 next.config.js
配置全局设置 CORS 标头。此方法会将 CORS 标头应用于所有 API 路由:
const nextConfig = {
async headers() {
return [
{
source: "/api/:path*",
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" }, // Allow all domains
{ key: "Access-Control-Allow-Methods", value: "GET,DELETE,PATCH,POST,PUT" },
{ key: "Access-Control-Allow-Headers", value: "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" },
],
},
];
},
};
module.exports = nextConfig;
src/middleware.js
import { NextResponse } from "next/server";
export function middleware(req) {
const res = NextResponse.next();
res.headers.append('Access-Control-Allow-Credentials', "true");
res.headers.append('Access-Control-Allow-Origin', '*'); // Allow all domains
res.headers.append('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT');
res.headers.append('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version');
if (req.method === 'OPTIONS') {
res.status(200).end();
return res;
}
return res;
}
export const config = {
matcher: '/api/:path*',
};
api/corsHandler.js:
const enableCors = (fn) => async (req, res) => {
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Origin', '*'); // Allow all domains
res.setHeader('Access-Control-Allow-Methods', 'GET,DELETE,PATCH,POST,PUT');
res.setHeader('Access-Control-Allow-Headers', 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version');
if (req.method === 'OPTIONS') {
res.status(200).end();
return;
}
return await fn(req, res);
};
const handler = (req, res) => {
const currentDate = new Date();
res.end(currentDate.toString());
};
module.exports = enableCors(handler);
vercel.json:
{
"headers": [
{
"source": "/api/(.*)",
"headers": [
{ "key": "Access-Control-Allow-Credentials", "value": "true" },
{ "key": "Access-Control-Allow-Origin", "value": "*" }, // Allow all domains
{ "key": "Access-Control-Allow-Methods", "value": "GET,DELETE,PATCH,POST,PUT" },
{ "key": "Access-Control-Allow-Headers", "value": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" }
]
}
]
}