练习 - 将 EF Core 添加到最小 API
你是公司的开发人员,你和你的公司都听说过新的最小 API。 你的经理要求你为其创建一个项目,以便你能够讨论是否在下一个项目上使用它。
注释
本模块使用 .NET CLI(命令行接口)和 Visual Studio Code 进行本地开发。 完成本模块后,你可以使用 Visual Studio (Windows)、Visual Studio for Mac (macOS) 来应用概念,或使用 Visual Studio Code(Windows、Linux 和 macOS)进行持续开发。
本模块使用 .NET 8.0 SDK。 通过在首选命令终端中运行以下命令,确保你已安装 .NET 8.0:
dotnet --list-sdks
将显示类似于以下示例的输出:
6.0.317 [C:\Program Files\dotnet\sdk]
7.0.401 [C:\Program Files\dotnet\sdk]
8.0.100 [C:\Program Files\dotnet\sdk]
确保列出了以 8
开头的版本。 如果未列出或找不到该命令, 请安装最新的 .NET 8.0 SDK。
启动项目
首先,需要创建项目。 已安装 .NET 6 并已准备就绪。 在本单元中,你将向披萨管理 API 添加数据持久性。
在终端中,通过运行
dotnet new
以下内容创建 Web API:dotnet new web -o PizzaStore -f net8.0
应会看到 PizzaStore 目录。
输入以下命令转到 PizzaStore 目录:
cd PizzaStore
安装 Swashbuckle 包:
dotnet add package Swashbuckle.AspNetCore --version 6.5.0
在 Visual Studio Code 中打开项目。
使用 Visual Studio Code 在项目根目录中创建 Pizza.cs 文件,并为其提供以下内容:
namespace PizzaStore.Models { public class Pizza { public int Id { get; set; } public string? Name { get; set; } public string? Description { get; set; } } }
前面的
Pizza
类是表示披萨的简单对象。 此代码是数据模型。 稍后,你将使用 Entity Framework (EF) Core 将此数据模型映射到数据库表。打开 Program.cs 并添加突出显示的代码:
using Microsoft.OpenApi.Models; var builder = WebApplication.CreateBuilder(args); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "PizzaStore API", Description = "Making the Pizzas you love", Version = "v1" }); }); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "PizzaStore API V1"); }); } app.MapGet("/", () => "Hello World!"); app.Run();
Visual Studio Code 可能会提示你添加资产以调试项目。 在对话框中选择
Yes
。
将 EF Core 添加到项目
若要将项存储在 to-do 列表中,请安装包 EntityFrameworkCore.InMemory
。
按 Ctrl+' 在 Visual Studio Code 中打开终端。 在新终端中,输入以下代码以添加 EF Core InMemory 包:
dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 8.0
using Microsoft.EntityFrameworkCore;
添加到Program.cs和Pizza.cs文件的顶部。将 EF Core 添加到项目后,可以将代码连接到要保存和查询的数据。 若要执行此步骤,请创建一个
PizzaDb
类。 该PizzaDb
类将执行以下任务:-
Pizzas
从数据库中的属性Pizza
列表中公开属性。 - 用于
UseInMemoryDatabase
连接内存中数据库存储。 只要应用正在运行,数据就存储在此处。
-
若要设置内存中数据库,请将以下代码添加到 Pizza.cs 文件底部(在最终
}
文件上方)。 命名空间中有两个PizzaStore.Models
类定义。class PizzaDb : DbContext { public PizzaDb(DbContextOptions options) : base(options) { } public DbSet<Pizza> Pizzas { get; set; } = null!; }
DbContext
表示用于查询和保存数据库中实体实例的连接或会话。添加到
using PizzaStore.Models;
Program.cs文件的顶部。在 Program.cs,在调用
AddSwaggerGen
之前,添加以下代码:builder.Services.AddDbContext<PizzaDb>(options => options.UseInMemoryDatabase("items"));
返回项列表
若要从披萨列表中的项目列表进行读取,请在调用上方添加以下代码以
app.Run();
添加“/pizzas”路由:app.MapGet("/pizzas", async (PizzaDb db) => await db.Pizzas.ToListAsync());
运行应用程序
确保已保存所有更改。 通过在终端中调用
dotnet run
来运行应用。 此作将生成应用并将其托管在 5000-5300 的端口上。 HTTPS 将在 7000-7300 范围内为其选择端口。注释
如果要覆盖随机端口选择行为,可以在 launchSettings.json 中设置要使用的端口。
dotnet run
下面是输出在终端中的情况:
Building... info: Microsoft.Hosting.Lifetime[14] Now listening on: https://localhost:7200 info: Microsoft.Hosting.Lifetime[14] Now listening on: http://localhost:5100 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down. info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development info: Microsoft.Hosting.Lifetime[0] Content root path: /<path>/PizzaStore
在浏览器中转到 https://localhost:{PORT}/swagger。 选择
GET /pizzas
按钮,然后 试用 并 执行。 你将看到列表在下方Response body
为空。在终端中,按 Ctrl+C 停止运行程序。
创建新项
让我们将代码添加到 POST
披萨列表的新项。 在 Program.cs中,在前面创建的代码下 app.MapGet
添加以下代码。
app.MapPost("/pizza", async (PizzaDb db, Pizza pizza) =>
{
await db.Pizzas.AddAsync(pizza);
await db.SaveChangesAsync();
return Results.Created($"/pizza/{pizza.Id}", pizza);
});
测试 API
请确保已保存所有更改并再次运行应用。 返回到 Swagger UI,现在应会看到 POST/pizza
。 若要向披萨列表添加新项目,请执行以下作:
选择 POST /pizza。
选择试用。
将请求正文替换为以下 JSON:
{ "name": "Pepperoni", "description": "A classic pepperoni pizza" }
选择“执行”。
若要读取列表中的项,
选择 GET /pizzas。
选择试用。
选择“执行”。
将
Response body
包括刚刚添加的项。[ { "id": 1, "name": "Pepperoni", "description": "A classic pepperoni pizza" } ]
在终端中按 Ctrl+C 停止运行应用。 对于本练习的其余部分,请根据需要停止并重启应用以测试更改。 请务必先保存所有更改
dotnet run
!
获取单个项
若要获取 id
项,请在前面创建的路由下 app.MapPost
添加代码。
app.MapGet("/pizza/{id}", async (PizzaDb db, int id) => await db.Pizzas.FindAsync(id));
按 ID 测试 GET
若要测试此作,可以转到 https://localhost:{PORT}/pizza/1 或使用 Swagger UI。 由于使用的是内存中数据库,因此如果重新启动应用程序,则之前创建的披萨将不会列出。 因此,需要使用 POST作再次添加它。
更新一项内容
若要更新现有项,请在创建的路由下 GET /pizza/{id}
添加代码:
app.MapPut("/pizza/{id}", async (PizzaDb db, Pizza updatepizza, int id) =>
{
var pizza = await db.Pizzas.FindAsync(id);
if (pizza is null) return Results.NotFound();
pizza.Name = updatepizza.Name;
pizza.Description = updatepizza.Description;
await db.SaveChangesAsync();
return Results.NoContent();
});
测试 PUT
在 Swagger UI 中选择 PUT /pizza/{id} 。
选择试用。
在 ID 文本框中,输入 1。
最后,更新
Request body
。 粘贴以下 JSON 并更改为name
Pineapple
。{ "id": 1, "name": "Pineapple" }
选择“执行”。
若要测试代码,请向下滚动到 GET /pizza/{id}
。 披萨现在有名字 Pineapple
。
删除项
若要删除现有项,请添加前面创建的代码 PUT /pizza/{id}
:
app.MapDelete("/pizza/{id}", async (PizzaDb db, int id) =>
{
var pizza = await db.Pizzas.FindAsync(id);
if (pizza is null)
{
return Results.NotFound();
}
db.Pizzas.Remove(pizza);
await db.SaveChangesAsync();
return Results.Ok();
});
测试 DELETE
现在,请尝试使用 Swagger 接口删除项。
在本单元中,你已将 EF Core 添加到现有的最小 API 应用程序,并使用内存中数据库来存储数据。 接下来,你将了解如何使用实际数据库来存储数据,以便在应用程序关闭之间保留。