如何将我的 Azure SQL 数据库连接到我的 Next TS 代码库

问题描述 投票:0回答:1

因此,我正在构建一个 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

typescript azure next.js azure-sql-database
1个回答
0
投票

我尝试了您的代码,并在更新示例数据后遇到了内部服务器错误。此问题可能是由于防火墙设置和

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);

}

enter image description here

添加此代码用于处理添加数据后的数据错误,使用此代码处理

P2002
错误和其他与数据相关的问题:

res.status(200).json({ message: "User created successfully", user });

} catch (error) {

console.error("Error creating user:", error);

enter image description here

将 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

enter image description here

  • 现在创建一个新的 API 路由来使用 SQl 数据字段处理表单提交,如
    pages/api/submit.ts
  • 在 Next.js 前端组件中创建一个表单来处理用户输入并将数据提交到您的 API 路由,例如
    components/UserForm.tsx
  • 使用
    UserForm
    和类
    pages/index.tsx
    来调用
    div
    文件中的
    form-container
    组件。

enter image description here

enter image description here

  • 使用 Next.js 作为后端或进行 Next.js curl 调用时,请确保配置 CORS 以避免错误。

请参阅本指南以在Next.js中实现CORS。

您可以使用

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" }
      ]
    }
  ]
}

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.