Logo
Section 1 / 6

添加、更新和删除数据

学习在 EF Core 中添加、更新和删除数据的基本操作。

导入

添加、更新和删除数据

学习在 EF Core 中添加、更新和删除数据的基本操作。

概述

在本课程中,我们将学习如何使用 EF Core 添加、更新和删除数据。每个上下文实例都包含一个 ChangeTracker。当我们对实体实例进行更改时,ChangeTracker 会跟踪这些更改。

...
创建、更新和删除操作

实体始终处于特定状态。例如,新实体处于 Added 状态(EntityState.Added),已修改的实体处于 Modified 状态(EntityState.Modified),而待删除的实体则处于 Deleted 状态(EntityState.Deleted)。当我们调用 DbContext.SaveChanges() 方法时,EF Core 会根据实体的 EntityState 值生成并执行相应的 INSERT、UPDATE 或 DELETE 语句。

本课程中的项目包含下表所示的数据:

员工

IdFirstNameLastNameAge
1MaxBello25
2FrancisOjukwu34
3MarthaBertha19

专辑

IdTitlePriceEmployeeId
1Blue Fire20002
2Raging Heart38503
3Fixated on you40001

注意:本课程项目输出包含示例代码的结果以及所使用的翻译后 SQL 查询的日志。

添加数据

我们将通过以下 C# 项目演示在 EF Core 中添加数据:

No configuration found for ID: 2595f0e93e232d18bbdc8adcb9dc2ae37dbf3a553151ddb2ff3e77f8fae28bde

点击上方的“运行”按钮,然后在终端中执行以下命令:

1dotnet run

以下是输出片段:

1执行了 DbCommand (7ms) [参数=[@p0='28', @p1='Susan' (长度 = 5), @p2='Fred' (长度 = 4)], 命令类型='文本', 超时时间='30'] 2INSERT INTO "Employees" ("Age", "FirstName", "LastName") 3VALUES (@p0, @p1, @p2); 4SELECT "Id" 5FROM "Employees" 6WHERE changes() = 1 AND "rowid" = last_insert_rowid();

注意该项目中的以下几点:

  • 在 Program.cs 的 第 15 行,我们使用 DbSet.Add 方法将一个新的 Employee 实体实例添加到 ArtistsContext。

  • 在 Program.cs 的 第 18 行,我们调用了 context.SaveChanges 方法,这导致 EF Core 将该员工插入数据库。上述片段显示了对应的 INSERT 语句。

  • 在 Program.cs 的 第 20 至 25 行,我们编写了代码用于显示所有现有员工。以下是结果片段:

1SELECT "e"."Id", "e"."Age", "e"."FirstName", "e"."LastName" 2FROM "Employees" AS "e" 3 4Id FirstName LastName Age 51 Max Bello 25 62 Francis Ojukwu 34 73 Martha Bertha 19 84 Susan Fred 28

上述代码片段的 第 8 行 显示了我们刚刚添加的员工。

添加相关实体的图谱

如果我们创建一个相关实体的图谱,并将其中一个实体添加到上下文中,整个图谱也会被一同添加。以下项目展示了这一点:

No configuration found for ID: fd1e11d22f6ef5f7037820cc37a4e30062b9eeb7f36f6ebd2d33d1ce8b5804db

点击上方的“运行”按钮,然后在终端中执行以下命令:

1dotnet run

以下是输出片段:

1执行了 DbCommand (12ms) [参数=[@p0='30', @p1='Steven' (长度 = 6), @p2='Brandy' (长度 = 6)], 命令类型='文本', 超时时间='30'] 2INSERT INTO "Employees" ("Age", "FirstName", "LastName") 3VALUES (@p0, @p1, @p2); 4SELECT "Id" 5FROM "Employees" 6WHERE changes() = 1 AND "rowid" = last_insert_rowid(); 7 8执行了 DbCommand (34ms) [参数=[@p3='3', @p4='2500', @p5='Lovely skys' (长度 = 11)], 命令类型='文本', 超时时间='30'] 9INSERT INTO "Albums" ("EmployeeId", "Price", "Title") 10VALUES (@p3, @p4, @p5); 11SELECT "Id" 12FROM "Albums" 13WHERE changes() = 1 AND "rowid" = last_insert_rowid(); 14 15执行了 DbCommand (34ms) [参数=[@p0='3', @p1='4000', @p2='Joy of the sun' (长度 = 14)], 命令类型='文本', 超时时间='30'] 16INSERT INTO "Albums" ("EmployeeId", "Price", "Title") 17VALUES (@p0, @p1, @p2); 18SELECT "Id" 19FROM "Albums" 20WHERE changes() = 1 AND "rowid" = last_insert_rowid();

注意该项目中的以下几点:

  • Program.cs 的 第 12 至 23 行 创建了一个新员工和两个相关的专辑。

  • 第 28 行将该员工添加到上下文中。由于专辑可通过 Employee.Albums 集合导航属性访问,因此它们也被自动添加。ChangeTracker 开始跟踪整个图谱。

  • Program.cs 的 第 30 行 调用了 context.SaveChanges,这导致 EF Core 将整个实体图谱插入数据库。

从输出中可以看出:

  • 执行了三条 INSERT 语句。

  • 第一条语句将新员工插入数据库。

  • 后续两条语句将该员工的专辑插入数据库。

最后,Program.cs 的 第 33 至 38 行 和 第 40 至 45 行 显示了所有员工和专辑数据。以下是输出片段:

1SELECT "e"."Id", "e"."Age", "e"."FirstName", "e"."LastName" 2FROM "Employees" AS "e" 3 4Id FirstName LastName Age 51 Max Bello 25 62 Francis Ojukwu 34 73 Martha Bertha 19 84 Susan Fred 28 95 Steven Brandy 30 10 11SELECT "a"."Id", "a"."EmployeeId", "a"."Price", "a"."Title" 12FROM "Albums" AS "a" 13 14Id Title Price EmployeeId 151 Blue Fire 2000 2 162 Raging Heart 3850 3 173 Fixated on you 4000 1 184 Lovely skys 2500 5 195 Joy of the sun 4000 5

从该片段中请注意以下几点:

  • 第 9 行 显示了新添加的员工。
  • 第 18 至 19 行 显示了新添加的专辑。

更新数据

EF Core 会自动检测由上下文跟踪的现有实体的更改。以下项目展示了这一点:

No configuration found for ID: e248386de12d9db017b5b9dbff8cc25d31d1fe59c28b8dd3191b3e619e4ac85a

点击上方项目中的“运行”按钮,然后在终端中执行以下命令:

1dotnet run

以下是输出片段:

1执行了 DbCommand (8ms) [参数=[@p1='1', @p0='Mark' (长度 = 4)], 命令类型='文本', 超时时间='30'] 2UPDATE "Employees" SET "FirstName" = @p0 3WHERE "Id" = @p1; 4SELECT changes(); 5 6SELECT "e"."Id", "e"."Age", "e"."FirstName", "e"."LastName" 7FROM "Employees" AS "e" 8Id FirstName LastName Age 91 Mark Bello 25 102 Francis Ojukwu 34 113 Martha Bertha 19 124 Susan Fred 28 135 Steven Brandy 30

注意该项目中的以下几点:

  • Program.cs 的 第 10 行 从 Employees 上下文中获取第一个员工。

  • 在 Program.cs 的 第 11 行,我们修改了所选员工的 FirstName 属性。ChangeTracker 检测到了这一更改。

  • Program.cs 的 第 14 行 将所有更改保存到数据库。

从输出片段中请注意以下几点:

  • 当我们修改 Employee 的 FirstName 属性时,EF Core 会将该员工的 EntityState 设置为 Modified。调用 context.SaveChanges 时,会生成所需的 UPDATE 语句。我们在上述片段的 第 2 至 3 行 中可以看到这一点。

  • 在同一片段的 第 9 行,可以看到 Max 已被更新为 Mark。

删除数据

DbSet.Remove 方法从上下文中删除实体实例。如果该实体尚未存在于数据库中,则它将从上下文中移除,且不会被插入数据库。如果该实体已存在于数据库中,则它将从上下文中移除,并在调用 context.SaveChanges 方法后从数据库中删除。以下项目展示了这一点:

No configuration found for ID: 8f6ea11aa00c6748487d86b4522a39d02716e85f52bba4e054af6be8441c0102

点击上方项目中的“运行”按钮,然后在终端中执行以下命令:

1dotnet run

以下是输出片段:

1执行了 DbCommand (39ms) [参数=[@p0='1'], 命令类型='文本', 超时时间='30'] 2DELETE FROM "Employees" 3WHERE "Id" = @p0; 4SELECT changes(); 5 6SELECT "e"."Id", "e"."Age", "e"."FirstName", "e"."LastName" 7FROM "Employees" AS "e" 8Id FirstName LastName Age 92 Francis Ojukwu 34 103 Martha Bertha 19

注意该项目中的以下几点:

  • Program.cs 的 第 11 行 的 DbSet.Remove 方法将所选员工的 EntityState 设置为 Deleted。

  • 在调用 context.SaveChanges(第 14 行)之后,DELETE 语句将所选员工从数据库中移除。从上述片段可以看出,“Mark Bello” 已不再作为员工存在。

查询数据

变更跟踪