项目简介

技术栈: ASP.NET Core Web API, Entity Framework Core, SQL Server

功能:

  1. 实现一个简单的CRUD API(例如:管理“待办事项”或“产品”)
  2. 支持基本的增删改查操作
  3. 使用Swagger生成API文档

学习重点:

  1. ASP.NET Core Web API的基本用法
  2. Entity Framework Core与数据库的交互
  3. RESTful API设计原则

本文涉及到的工具

  • Visual Studio
  • PowerShell
  • Edge浏览器

本文的开发平台 Windows 10 企业版,64位

推荐理由: 这是.NET后端开发的基础,适合新手快速入门。

相关技术栈简介

ASP .NET Core Web API

用于构建基于 HTTP 协议的 Web 服务,为各种客户端(如浏览器、移动应用、IoT 设备等)提供数据和功能。

简单来说,你可以把 Web API 想象成一个“数据中转站”:

  1. 客户端 (例如手机 App) 发送请求 (例如获取用户信息)。
  2. Web API 接收请求,处理请求 (例如从数据库查询数据),并返回响应 (例如 JSON 格式的用户信息)。
  3. 客户端 接收响应,并展示给用户。

Entity Framework Core

Entity Framework Core (EF Core) 是一个轻量级、可扩展、跨平台的对象关系映射 (ORM) 框架,它简化了 .NET 开发人员与数据库的交互。

简单来说,EF Core 就像一个“翻译官”:

  1. 你 使用 C# 对象 (例如 User 类) 来操作数据。
  2. EF Core 将这些操作转换成 SQL 语句,并与数据库进行交互。
  3. 数据库 执行 SQL 语句,并返回结果。
  4. EF Core 将结果转换成 C# 对象,供你使用。

EF Core 的优势:

  1. 简化数据库操作: 使用 C# 对象操作数据库,无需编写复杂的 SQL 语句。
  2. 提高开发效率: 自动生成数据库 schema、跟踪对象状态、处理并发等
  3. 支持多种数据库: SQL Server、MySQL、PostgreSQL、SQLite 等。
  4. 跨平台: 可以在 Windows、Linux 和 macOS 上运行。
  5. 开源: 活跃的社区和丰富的资源。

SQL Service

SQL Server 是由 Microsoft 开发的关系型数据库管理系统 (RDBMS),它用于存储、管理和检索数据。

简单来说,SQL Server 就像一个“数据仓库”:

  1. 你 使用 SQL 语言 (结构化查询语言) 与数据库进行交互。
  2. SQL Server 接收 SQL 语句,执行操作 (例如查询数据、插入数据、更新数据、删除数据),并返回结果。
  3. 你 接收结果,并进行处理或展示。

Swagger

Swagger 是一套用于描述和文档化 RESTful API 的开源工具集。它可以帮助开发者更轻松地设计、构建、测试和使用 API。

简单来说,Swagger 就像一个“API 说明书”:

  • API 提供者 使用 Swagger 描述 API 的接口、参数、返回值等信息。
  • Swagger 生成交互式文档,方便开发者查看和理解 API。
  • API 使用者 可以使用 Swagger 文档快速上手 API,并进行测试和调试。

项目构建步骤

安装CLI工具

  1. 单独安装CLI,不依靠Visual Studio Installer直接安装
  2. 使用Visual Studio直接安装包含了CLI的.NET开发组件(推荐,仅在Windows系统可行)

安装成功后,打开PowerShell,输入命令‘dotnet –info’来检测是否安装成功!

dotnet --info命令:显示 .NET 信息

如果出现类似的输出,这说明安装成功(见下图)

如果出现了以下情况:

  1. 在“.NET SDKs installed“一栏中显示“No SDKs were found.”
  2. 使用创建项目命令dotnet new Web -n TestDotnetInstall收到如下图的信息
  3. 直接使用VS创建Web API项目收到了如下图的报错

可能是CLI确实安装好了,但是系统默认使用的是基于32位的CLI工具,它无法在64位的系统上运行

解决方法:

  1. 打开”环境变量”界面
  2. 打开”系统变量“一栏中的“Path”变量
  3. 检查是否有两个地址“C:\Program Files\dotnet\”和“C:\Program Files (x86)\dotnet”,前者是基于64位系统的CLI工具的文件地址,后者则是基于32位系统的,确保前者在后者前面或者直接删除后者

之后重启PowerShell使更改生效,再输入命令检查是否安装成功

正式创建项目

  1. 使用命令创建(不推荐默认情况该方法创建的项目不包含.sln文件) dotnet new Web -n TodoApi 该命令会在当前文件夹里创建一个名为TodoApi的Web API项目文件夹

  2. 使用VS创建项目(默认包含.sln文件)

如何在由命令创建的项目中添加.sln文件

毕竟VS作为一个强大的开发工具,可以我们的后续开发提供很大的帮助,但没有.sln文件我们就无法用VS打开项目

  • 创建 Web API 项目 首先,使用以下命令创建一个新的 ASP.NET Core Web API 项目:

    dotnet new webapi -n MyWebApi

    这将在当前目录下创建一个名为 MyWebApi 的文件夹,并在其中生成 Web API 项目文件。

  • 创建解决方案文件 接下来,进入项目目录并创建一个新的解决方案文件:

    cd MyWebApi
    dotnet new sln -n MyWebApiSolution

这将在当前目录下创建一个名为 MyWebApiSolution.sln 的解决方案文件。

  • 将项目添加到解决方案

最后,将 Web API 项目添加到解决方案中:

dotnet sln MyWebApiSolution.sln add MyWebApi.csproj
  • 验证

你可以使用以下命令验证解决方案文件是否正确创建并包含项目:

dotnet sln list

这将列出解决方案中的所有项目。

安装所需的包

在简介介绍的Entity Framework Core、SQL Server和Swagger等工具要想在.NET项目中使用得要通过NuGet下载并安装对应的包

通过命令安装 dotnet add package <包名>

dotnet package search <搜索词>: 搜索与搜索词匹配的包

dotnet list package: 可以查看当前项目或解决方法所有包引用

安装支持SQL Server的EF Core: dotnet add package Microsoft.EntityFrameworkCore.SqlServer

安装Swagger相关包 dotnet add package Swashbuckle.AspNetCore

安装dotnet-ef工具来实现“迁移”(migrations) “迁移”(migrations)可以简单理解为“将实体类的修改同步(迁移)到对应的数据库中,从而实现在代码中就可以定义数据库架构的变更”

想要使用dotnet工具得安装Microsoft.EntityFrameworkCore.Design框架 dotnet add package Microsoft.EntityFrameworkCore.Design

安装dotnet-ef工具(需要管理员权限,全局安装) dotnet tool install --global dotnet-ef

检查dotnet-ef工具是否安装成功 dotnet ef -v

要注意的一点!Microsoft.EntityFrameworkCore.Design包的版本要与dotnet-ef工具版本一致。

查看项目所有包引用,检查需要的包是否安装好和版本是否正确 dotnet list package

正式开始编写代码

下面是本次项目得使用的EF Core框架的内容

  • DbSet<T> 是一个泛型类,代表数据库中的一张表,T 是表的实体类型(数据类)。通过 DbSet<T>,你可以对表中的数据进行增删改查操作。
  • DbContext 是一个核心类,它代表与数据库的会话,并提供了对数据库进行操作的主要入口点。
  • ControllerBase 是一个基类,用于创建处理 HTTP 请求的控制器。它提供了许多常用的属性和方法,方便开发者编写 Web API 控制器。

在项目中创建文件夹Model,在其中创建一个数据类TodoItem.cs, 代表着一项代办事务, 作为数据类供DbSet<T>使用

namespace TodoApi.Models
{
    public class TodoItem
    {
        public int Id { get; set; } // 唯一标识
        public string? Title { get; set; } // 待办事项标题
        public bool IsCompleted { get; set; } // 是否完成
    }
}

之后在项目文件夹中创建文件夹Data,在其中创建一个TodoContext.cs, 它负责与数据库的对话

using Microsoft.EntityFrameworkCore;
using TodoApi.Models;

namespace TodoApi.Data
{
    public class TodoContext : DbContext
    {
        public TodoContext(DbContextOptions<TodoContext> options) : base(options) { }

        public DbSet<TodoItem> TodoItems { get; set; } // 表示数据库中的TodoItems表
    }
}

最后在项目文件夹中文件夹Controllers,在其中创建一个TodoController类:

using Microsoft.AspNetCore.Mvc;
using TodoApi.Data;
using TodoApi.Models;

namespace TodoApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class TodoController : ControllerBase
    {
        private readonly TodoContext _context;

        public TodoController(TodoContext context)
        {
            _context = context;
        }

        // 获取所有待办事项
        [HttpGet]
        public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
        {
            return await _context.TodoItems.ToListAsync();
        }

        // 获取单个待办事项
        [HttpGet("{id}")]
        public async Task<ActionResult<TodoItem>> GetTodoItem(int id)
        {
            var todoItem = await _context.TodoItems.FindAsync(id);
            if (todoItem == null)
            {
                return NotFound();
            }
            return todoItem;
        }

        // 创建待办事项
        [HttpPost]
        public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
        {
            _context.TodoItems.Add(todoItem);
            await _context.SaveChangesAsync();
            return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
        }

        // 更新待办事项
        [HttpPut("{id}")]
        public async Task<IActionResult> PutTodoItem(int id, TodoItem todoItem)
        {
            if (id != todoItem.Id)
            {
                return BadRequest();
            }

            _context.Entry(todoItem).State = EntityState.Modified;
            await _context.SaveChangesAsync();
            return NoContent();
        }

        // 删除待办事项
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteTodoItem(int id)
        {
            var todoItem = await _context.TodoItems.FindAsync(id);
            if (todoItem == null)
            {
                return NotFound();
            }

            _context.TodoItems.Remove(todoItem);
            await _context.SaveChangesAsync();
            return NoContent();
        }
    }
}

编写Program.cs文件

在Program.cs文件中注册数据库上下文 Programe.cs文件是ASP .NET Web API项目的入口点,负责配置和启动应用程序。 在本次项目我们要实现在开发环境下使用浏览器本地访问项目并通过Swagger自动生成的API文档来测试API能否在数据库上进行增删查改的操作,我们需要完成以下操作:

  • 创建 WebApplicationBuilder对象builder来配置相关服务

    1. 注册数据库上下文,实现项目与数据库的连接
    2. 将项目运行环境设置为开发环境
    3. 添加Swagger服务
    4. 添加 CORS 策略(这里为了测试,接受任何地方AllowAnyOrign、任何方法AllowAnyMethod、任何请求头(AllowAnyHeader)的请求)
    5. 注册MVC控制器,用于处理Web API请求
  • 通过builder来构建WebApplication实例对象app来添加相关中间件

    1. 启用CORS策略
    2. 启用Swagger
    3. 启用SwaggerUI,并配置其UI文件的路径
    4. 启用“强制HTTP重定向HTTPS”
    5. 启用“允许访问静态文件”
    6. 启用授权,用于通过身份验证
    7. 启用“API控制器映射到路由,允许API处理请求”
  • 最后运行项目

具体代码:

using TodoApi.Data;
using Microsoft.EntityFrameworkCore;

// 注册数据库上下文
var builder = WebApplication.CreateBuilder(args);

// 强制设置为开发环境
builder.Environment.EnvironmentName = "Development";

// 添加数据库上下文
builder.Services.AddDbContext<TodoContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

// 添加控制器
builder.Services.AddControllers();

// 添加 Swagger
builder.Services.AddSwaggerGen();

// 构建项目
var app = builder.Build();

// 启用 Swagger
app.UseSwagger();

// 启用 SwaggerUI并配置UI文件的路径 
app.UseSwaggerUI(options =>
{
    options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1");
    options.RoutePrefix = "swagger"; // 确保路由正确
});

// 强制 HTTP 请求跳转到 HTTPS(需要 SSL 证书)。
app.UseHttpsRedirection(); 

// 允许访问 wwwroot 目录下的静态文件(例如 CSS、JS),为了让Swagger能访问到ui文件
app.UseStaticFiles();

// 启用授权(如果 API 需要身份验证)。
app.UseAuthorization();

// 将 API 控制器映射到路由,允许 API 处理请求。
app.MapControllers();

// 启动项目
app.Run();

项目json配置

配置appsetting.json文件

配置数据库连接
"ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApi;Trusted_Connection=True;"
  },

相关参数介绍

  • Server=(localdb)\\mssqllocaldb; : 项目要链接的数据库实例的名称,这里我们使用SQL Server的一个默认数据库实例”(localdb)\mssqllocaldb”,这个实例不需要复杂的、像完整SQL Server实例的配置,并且数据库文件存放于用户文件夹下,适合用户开发和测试。当然你也可以自行创建数据库实例跟数据库来使用。
  • Data=TodoApi; : 要连接的数据库的名称,在后文创建数据库迁移时会创建所需的TodoApi数据库
  • Trusted_Connection = true; : 是否信任连接

LocalDB的常见问题

  • 实例未启动,使用下面的命令启动即可(管理员模式下操作)

    sqllocaldb start massqllocaldb
  • 未安装LocalDB

    • 安装 Visual Studio 时选择“数据存储和处理”工作负载。
    • 单独下载并安装 SQL Server Express。
配置Kestrel服务器来响应HTTP请求

在 ASP.NET Core 中,appsettings.json 文件中的 Kestrel 属性用于配置 Kestrel 服务器的行为。Kestrel 是 ASP.NET Core 默认的跨平台 web 服务器,用于处理 HTTP 请求。

  • 示例:

    {
    "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "Https": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "path/to/certificate.pfx",
          "Password": "your_password"
        }
      }
    },
    "Limits": {
      "MaxConcurrentConnections": 100,
      "MaxRequestBodySize": 10485760
    },
    "AllowSynchronousIO": false
    }
    }

    各项属性介绍

  • Endpoints: 用于配置Kestrel监听的终结点(Endpoints),包括HTTP和HTTP。

  • Url: 指定监听的URL,可在这里配置监听的端口。

  • Certificate:配置 HTTPS 使用的证书。

  • Limits: 用于配置Kestrel的性能和行为限制

  • MaxConcurrentConnections: 最大并发连接数。

  • MaxRequestBodySize: 请求体的最大大小(字节为单位)。

  • MaxRequesBufferSzieMaxResponseBufferSize: 请求和响应的最大缓冲区大小。

  • AllowSynchronouslO: 控制是否允许同步I/O操作,默认值是false建议保持默认值以避免性能问题

  • Certificates: 配置HTTPS使用的证书

由于本文只是现在本地运行并访问,所有只需要按下面配置来就可以了

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=TodoApi;Trusted_Connection=True;"
  },

  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:6001"
      },
      "Https": {
        "Url": "https://localhost:6002"
      }
    }
  }
}

注意!!监听URL地址的端口不可以与其他程序有冲突!!!

查看更多配置属性

配置lauchSettings.json文件(可选)

lauchSettings.json文件主要是用于开发环境的配置,定义了Visual Studio或者使用dotnet run命令启动应用程序时的行为。 优先级比appsetting.json要低,如果两个文件同时配置了同一项内容(比如Kestrel中的Url与profiles中的applicationUrl都是指定项目监听的URL地址),则以appsetting.json的配置为主

所以本文以默认的lauchSettings.json文件的配置即可

创建数据库迁移

前文我们已经安装好dotnet-ef工具及其相关包,执行下面命令即可创建数据库迁移,InitialCreate是迁移的名称 由于前文在appsetting.json文件中配置好了数据库连接字符串,如果在创建迁移时目标数据库实例没有对应的数据库或者表会在一步会自动创建 dotnet ef migrations add InitialCreate

更新数据库,将在代码中对实体类的更改转移到数据库架构中 dotnet ef database update

注意:每次修改了代码中的实体类要想把更改带入到数据库中需要先移除原有的迁移再执行上面的两行命令重新创建迁移与更新数据库 移除迁移命令: dotnet ef migrations remove <Name>

参考文章与资料

VS2022中解决方案显示0项目 | 找不到指定的SDK“Microsoft.NET.Sdk” 「C#」EF Core的“迁移”(Migration)