跳至内容

CRUD

此页面描述了如何使用生成的 Prisma Client API 执行 CRUD 操作。CRUD 是一个首字母缩略词,代表

有关所有可用方法的完整列表,请参阅客户端 API 参考文档

示例模式和提供程序

所有示例都基于以下 Prisma 模式

展开以查看模式 (schema.prisma)
prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "dart run orm"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id           Int      @id @default(autoincrement())
  email        String   @unique
  name         String?
  age          Int?
  role         Role     @default(USER)
  posts        Post[]
  Profile      Profile?
  country      String?
  city         String?
  profileViews Int      @default(0)
}

model Post {
  id         Int        @id @default(autoincrement())
  title      String
  content    String?
  published  Boolean    @default(false)
  author     User?      @relation(fields: [authorId], references: [id])
  authorId   Int?
  categories Category[]
  views      Int        @default(0)
  likes      Int        @default(0)
  tags       String[]   @default([])
}

model Profile {
  id     Int     @id @default(autoincrement())
  bio    String?
  user   User    @relation(fields: [userId], references: [id])
  userId Int     @unique
}

model Category {
  id    Int    @id @default(autoincrement())
  name  String @unique
  posts Post[]
}

enum Role {
  USER
  ADMIN
}
展开以查看提供程序 (prisma.dart)
dart
import 'dart:async';

import 'prisma/generated_dart_client/client.dart';

/// Create a new instance of PrismaClient
final _client = PrismaClient();

/// Provide a PrismaClient instance to a function.
///
/// Wrapped in a function to ensure that the instance is diconnected
/// after the function is done.
FutureOr<T> providePrisma<T>(
    FutureOr<T> Function(PrismaClient prisma) main) async {
  try {
    return await main(_client);
  } finally {
    await _client.$disconnect();
  }
}

创建

创建单个记录

以下查询创建 (create) User 模型的单个记录,其中包含两个字段

dart
final user = await prisma.user.create(
  data: PrismaUnion.$1(UserCreateInput(
    email: "seven@odroe.com",
    name: PrismaUnion.$1("Seven Du"),
  )),
);
显示查询结果
{id: 1, email: seven@odroe.com, name: Seven Du, role: USER}

用户的 id 由数据库自动生成。

创建多个记录

以下 createMany 查询创建多个用户并跳过任何重复项(email 必须唯一)

dart
final affectedRows = await prisma.user.createMany(
  data: PrismaUnion.$2([
    UserCreateManyInput(
        name: PrismaUnion.$1("Bob1"), email: "bob@prisma.pub"),
    UserCreateManyInput(
        name: PrismaUnion.$1("Bob2"), email: "bob@prisma.pub"),
    UserCreateManyInput(
        name: PrismaUnion.$1("Yewande"), email: "yewande@prisma.pub"),
    UserCreateManyInput(
        name: PrismaUnion.$1("Ange"), email: "ange@prisma.pub"),
  ]),
  skipDuplicates: true, // Skip 'Bob2'
);
显示查询结果
{count: 3}

提示

使用 **MongoDB** 和 **SQL Server** 时不支持 skipDuplicates

有关同时创建记录和一个或多个相关记录的信息,请参阅相关查询 -> 嵌套写入

读取

按 ID 或唯一字段获取记录

以下查询按 ID 或唯一字段返回单个记录 (findUnique)

dart
final user = await prisma.user.findUnique(
  where: UserWhereUniqueInput(id: 1),
);
dart
final user = await prisma.user.findUnique(
  where: UserWhereUniqueInput(email: "seven@odroe.com"),
);

获取所有记录

以下 findMany 查询返回所有 User 记录

dart
final users = await prisma.user.findMany();

您还可以对结果进行分页

获取与特定条件匹配的第一条记录

以下 findFirst 查询返回最近创建的 User,该用户至少有一篇 post 的点赞数超过 100

  1. 按降序 ID(最大值优先)对用户进行排序 - 最大的 ID 是最近创建的用户。
  2. 过滤至少有一篇点赞数超过 100 的帖子的用户。
dart
final user = await prisma.user.findFirst(
  where: UserWhereInput(
    posts: PostListRelationFilter(
      some: PostWhereInput(
        likes: PrismaUnion.$1(
          IntFilter(gt: PrismaUnion.$1(100)),
        ),
      ),
    ),
  ),
  orderBy: PrismaUnion.$2(
    UserOrderByWithRelationInput(id: SortOrder.desc),
  ),
);

获取过滤后的记录列表

Prisma Dart 客户端支持对记录字段和相关字段进行过滤

按单个字段值过滤

以下查询返回所有电子邮件以 "odroe.com" 结尾的 User 记录

dart
final users = await prisma.user.findMany(
  where: UserWhereInput(
    email: PrismaUnion.$1(
      StringFilter(endsWith: PrismaUnion.$1('@odroe.com')),
    ),
  ),
);

按多个字段值过滤

以下查询使用运算符组合返回名称以 S 开头或角色为 ADMIN 的用户

dart
final users = await prisma.user.findMany(
  where: UserWhereInput(
    OR: [
      UserWhereInput(
        name: PrismaUnion.$1(
          StringNullableFilter(startsWith: PrismaUnion.$1("S")),
        ),
      ),
      UserWhereInput(
        role: PrismaUnion.$2(Role.admin),
      ),
    ],
  ),
);

以下查询返回电子邮件域名是 odroe.com 且至少有一篇未发布的帖子 (somo) 的用户

dart
final users = await prisma.user.findMany(
  where: UserWhereInput(
    email: PrismaUnion.$1(
      StringFilter(endsWith: PrismaUnion.$1("@odroe.com")),
    ),
    posts: PostListRelationFilter(
      some: PostWhereInput(
        published: PrismaUnion.$2(false),
      ),
    ),
  ),
);

有关根据相关字段值进行过滤的更多示例,请参阅使用关系

选择字段子集

以下 findUnique 查询使用 select 返回特定 User 记录的 nameemail 字段

dart
final user = await prisma.user.findUnique(
  where: UserWhereUniqueInput(email: "seven@odroe.com"),
  select: UserSelect(
    name: true,
    email: true,
  ),
);

有关包含关系的更多信息,请参阅

以下查询使用嵌套选择返回

  • Useremail 字段
  • 每个 Postlikes 字段
dart
final user = await prisma.user.findUnique(
  where: UserWhereUniqueInput(email: "seven@odroe.com"),
  select: UserSelect(
    email: true,
    posts: PrismaUnion.$2(
      UserPostsArgs(
        select: PostSelect(likes: true),
      ),
    ),
  ),
);

以下查询返回所有 ADMIN 用户并在结果中包含每个用户的帖子

dart
final users = await prisma.user.findMany(
  where: UserWhereInput(
    role: PrismaUnion.$2(Role.admin),
  ),
  include: UserInclude(
    posts: PrismaUnion.$1(true),
  ),
);

有关包含关系的更多信息,请参阅选择字段 -> 嵌套读取

更新

更新单个记录

以下查询使用 update 通过 email 查找并更新单个 User 记录

dart
final updatedUser = await prisma.user.update(
  where: UserWhereUniqueInput(email: "seven@odroe.com"),
  data: PrismaUnion.$2(
    UserUncheckedUpdateInput(
      name: PrismaUnion.$1("Seven Odroe"),
    ),
  ),
);
显示查询结果
{id: 1, email: seven@odroe.com, name: Seven Odroe, role: USER}

更新多个记录

以下查询使用 updateMany 将所有电子邮件中包含 odroe.com 的 User 记录的 role 更新为 ADMIN

dart
final affectedRows = await prisma.user.updateMany(
  where: UserWhereInput(
    email: PrismaUnion.$1(
      StringFilter(endsWith: PrismaUnion.$1("@odroe.com")),
    ),
  ),
  data: PrismaUnion.$1(
    UserUpdateManyMutationInput(
      role: PrismaUnion.$1(Role.admin),
    ),
  ),
);
显示查询结果
{ count: 1 }

更新或创建记录

以下查询使用 upsert 更新具有特定 email 地址的 User 记录,如果该 User 记录不存在,则创建该记录

dart
final user = await prisma.user.upsert(
  where: UserWhereUniqueInput(email: "medz@prisma.pub"),
  create: PrismaUnion.$1(UserCreateInput(
    email: "medz@prisma.pub",
    name: PrismaUnion.$1("Seven at GitHub username"),
  )),
  update: PrismaUnion.$1(
    UserUpdateInput(
      name: PrismaUnion.$1("Seven at GitHub username"),
    ),
  ),
);

从 4.6.0 版开始,Prisma 在可能的情况下使用数据库本机 SQL 命令执行 upsert。

了解更多

查找或创建

您可以使用 Dart extension 创建 findOrCreate 方法

dart
extension UserFindOrCreate on UserDelegate {
  ActionClient<User> findOrCreate({
    required UserWhereUniqueInput where,
    required UserCreateInput data,
    // ... More fields can be added here
  }) {
    return upsert(
      where: where,
      create: PrismaUnion.$1(data),
      // Create a empty update input, make sure the update input is not null
      update: PrismaUnion.$2(UserUncheckedUpdateInput()),
    );
  }
}

现在您可以使用 findOrCreate 方法

dart
final user = await prisma.user.findOrCreate(
  where: UserWhereUniqueInput(email: "seven@odroe.com"),
  data: UserCreateInput(
    email: "seven@odroe.com",
    name: PrismaUnion.$1("Seven Du"),
  ),
);

警告

Prisma 没有 findOrCreate 查询。您可以使用 upsert 作为解决方法。要使 upsert 的行为类似于 findOrCreate 方法,请向 upsert 提供一个空的更新参数。

更新数字字段

使用原子数字运算来更新数字字段 **基于其当前值** - 例如,incrementmultiply。以下查询将 viewslikes 字段增加 1

dart
final affectedRows = await prisma.post.updateMany(
  data: PrismaUnion.$1(
    PostUpdateManyMutationInput(
      views: PrismaUnion.$2(
        IntFieldUpdateOperationsInput(increment: 1),
      ),
      likes: PrismaUnion.$2(
        IntFieldUpdateOperationsInput(increment: 1),
      ),
    ),
  ),
);

删除

删除单个记录

以下查询使用 delete 删除单个 User 记录

dart
final deletedUser = await prisma.user.delete(
  where: UserWhereUniqueInput(
    email: "bob@prusma.pub",
  ),
);

尝试删除一个或多个帖子的用户会导致错误,因为每个帖子都需要一个作者 - 请参阅 👉 级联删除

删除多个记录

以下查询使用 deleteMany 删除所有 Use 记录,其中 email 域名是 odroe.com

dart
final affectedRows = await prisma.user.deleteMany(
  where: UserWhereInput(
    email: PrismaUnion.$1(
      StringFilter(
        endsWith: PrismaUnion.$1('@odroe.com'),
      ),
    ),
  ),
);

尝试删除一个或多个帖子的用户会导致错误,因为每个帖子都需要一个作者 - 请参阅 👉 级联删除

删除所有记录

以下查询使用 deleteMany 删除所有 User 记录

dart
final affectedRows = await prisma.user.deleteMany();

请注意,如果用户有任何相关记录(例如帖子),此查询将失败。在这种情况下,您需要先删除相关记录

以下查询使用 delete 删除单个 User 记录

dart
final deletedUser = await prisma.user.delete(
  where: UserWhereUniqueInput(
    email: "bob@prusma.pub",
  ),
);

但是,示例模式在 PostUser 之间包含一个 **必需的关系**,这意味着您不能删除包含帖子的用户

文本
The change you are trying to make would violate the required relation 'PostToUser' between the `Post` and `User` models.

要解决此错误,您可以

  1. 使关系可选
    prisma
    model Post {
         id       Int   @id @default(autoincrement())
         author   User? @relation(fields: [authorId], references: [id]) 
         authorId Int?
         author   User  @relation(fields: [authorId], references: [id]) 
         authorId Int
    }
  2. 在删除用户之前将帖子的作者更改为其他用户。
  3. 在事务中使用两个单独的查询删除用户及其所有帖子(所有查询都必须成功)
    dart
    await prisma.$transaction((prisma) async {
         await prisma.post.deleteMany();
         await prisma.user.deleteMany();
    });

不可序列化的查询值

Prisma Client Dart 支持以下不可序列化的查询值

dart
final data = await prisma.user.findMany().unserialized();

所有模型操作都支持 unserialized 方法。

在 BSD-3-Clause 许可证下发布