当前位置: 首页 > news >正文

第01章 01学习笔记:使用控制器进行 Web 开发简介

第01章 01学习笔记:使用控制器进行 Web 开发简介

板块①:本章地图

一句话定位

本书的 地基章——搭建开发环境、理解 ASP.NET Core 技术栈全貌、构建 Northwind 实体数据模型,为后续全部 14 章提供数据层基础。

前置依赖清单表

序号 前置知识点 来源章节 当前状态(已掌握/需回顾/全新) 版本要求
1 C# 基础语法(类、接口、特性、泛型、正则表达式) 外部 自评 C# 12+.NET 9
2 .NET 项目体系(.csproj / .sln / classlib / mvc 模板) 外部 自评 .NET SDK 9.0
3 NuGet 包管理基础(PackageReference / 版本号语义) 外部 自评
4 SQL Server 与 T-SQL 基础(数据库/表/连接) 外部 自评 SQL Server 2019+
5 Docker 基础概念(image / container / port mapping) 外部 自评 Docker Engine 24+
6 EF Core 基础(DbContext / DbSet / OnConfiguring) 外部 自评 EF Core 9.0.0
7 DI / IoC 基础(服务注册与解析) 外部 自评
8 单元测试基础(AAA 模式 / Assert) 外部 自评 xUnit 2.9+

版本说明

本章基于 .NET 9(STS) 编写,但作者同时标注 .NET 8(LTS)兼容。.NET 9 新增 HybridCache、Keyed DI、富文本日志格式等特性,但本章尚未深入这些。CPM(Central Package Management)为 .NET 8+ 的正式特性。

运行环境

组件 版本要求 安装命令
.NET SDK 9.0 (STS) 或 8.0 (LTS) winget install Microsoft.DotNet.SDK.9
Docker Desktop 4.33.1+ https://docs.docker.com/engine/install/
Azure SQL Edge latest docker pull mcr.microsoft.com/azure-sql-edge:latest
dotnet-ef CLI 9.0.0 dotnet tool install --global dotnet-ef
VS Code / VS 2022 最新稳定版
Git 2.0+ https://git-scm.com/download

板块②:核心概念深度卡


概念卡片 1:ASP.NET Core 历史演进

属性 说明
概念名 ASP.NET Core 历史演进 / ASP.NET Core History
稳定性 稳定(已形成共识的历史叙事)
全书追踪 Ch1 首次出现 → Ch8 深入(DI/管道/Aspire)

第一层(一句话直击本质):ASP.NET Core 是从 2016 年 .NET Core 1.0 开始的全新跨平台 Web 框架,历经 8 个大版本演进至 .NET 9,完全重写了 ASP.NET 技术栈。

第二层(核心机制展开):

ASP.NET 演进时间线:
1996 ─ ASP (Active Server Pages)          ← 脚本式,仅 Windows
2002 ─ ASP.NET Web Forms                   ← 事件驱动,拖控件
2009 ─ ASP.NET MVC 1.0                     ← MVC 模式引入
2012 ─ ASP.NET Web API                     ← REST 支持
2013 ─ SignalR                             ← 实时通信
2014 ─ OWIN (Open Web Interface for .NET) ← 解耦服务器与应用
2016 ─ ASP.NET Core 1.0 (.NET Core)       ← 全新跨平台运行时
2017 ─ ASP.NET Core 2.0 (.NET Standard 2) ← 统一 API 表面
2019 ─ ASP.NET Core 3.0 (仅 Core)         ← 彻底告别 .NET Framework
2020 ─ .NET 5 (跳过 Core 4)               ← "One .NET" 统一愿景
2021 ─ .NET 6 (LTS)                        ← 首个 LTS 统一定稿
2022 ─ .NET 7 (STS)                        ← 性能大幅提升
2023 ─ .NET 8 (LTS)                        ← 第二个 LTS
2024 ─ .NET 9 (STS)                        ← 本书基准版本

核心变化:从仅 Windows 的 System.Web → 跨平台的 Microsoft.AspNetCore,IIS 从宿主变反向代理,管道从 HttpModules → Middleware。

第三层(架构本质):ASP.NET Core 的设计哲学是「Modular, Cross-platform, High-performance」。它与旧 ASP.NET 的本质区别在于:不再依赖 System.Web.dll(这个 Win32-only 的庞然大物),而是基于 Microsoft.AspNetCore.App 共享框架(NuGet 元包)。这种模块化设计使得框架可以按需加载,启动速度更快,内存占用更低,且天然支持 Docker/Linux 部署。


概念卡片 2:Kestrel Web Server

属性 说明
概念名 Kestrel Web Server / Kestrel 跨平台服务器
稳定性 稳定(自 Core 1.0 起即默认服务器)
全书追踪 Ch1 首次出现 → Ch8 深入(容器化部署)

第一层(一句话直击本质):Kestrel 是 ASP.NET Core 内置的跨平台、高性能 HTTP 服务器,采用 libuv(现已改为托管 Socket)实现异步 I/O。

第二层(核心机制展开):

ASP.NET Core 支持三种 Web 服务器:

服务器 平台 用途
Kestrel 跨平台 默认内部服务器,直接处理 HTTP 请求
HTTP.sys 仅 Windows 基于 Windows 内核驱动,不需要反向代理即可暴露给 Internet
IIS (in-process) 仅 Windows 将 ASP.NET Core 应用直接运行在 IIS 工作进程内

典型部署模式:Internet → IIS/Nginx/Apache(反向代理)→ Kestrel(应用服务器)

第三层(架构本质):Kestrel 处于 ASP.NET Core 管道的最前端。它的设计遵循 Unix 哲学——"做一件事并做好":只处理 HTTP 协议解析和 I/O,所有中间件逻辑(路由、认证、MVC 等)委托给上层管道。这种分层使得 Kestrel 可以用 C 实现的托管 Socket 替代 libuv(自 Core 2.1 起),进一步降低内存分配和延迟。


概念卡片 3:ASP.NET Core 技术选型全景

属性 说明
概念名 ASP.NET Core 技术选型 / Technology Options
稳定性 稳定(框架已定型)
全书追踪 Ch1 概述 → Ch2-4(MVC)→ Ch9(Web API)→ Ch10(OData)→ Ch11(FastEndpoints)

第一层(一句话直击本质):.NET 开发者构建 Web 应用有五种主流范式——MVC、Razor Pages、Blazor、Web API、Minimal API——各有适用场景,可混合使用。

第二层(核心机制展开):

范式 特点 适用场景 本书章节
MVC Controller + View 分工,成熟生态 传统服务端渲染网站 Ch2-8
Razor Pages 页面级 Model,比 MVC 简洁 简单页面/表单 Ch2(对比)
Blazor C# 替代 JavaScript 运行于浏览器 SPA(服务器端或 WebAssembly) Ch1 提及
Web API / Minimal API RESTful 服务,无 UI 后端 API / 微服务 Ch9-12
FastEndpoints 高性能端点框架,REPR 模式 替代 Minimal API / MVC 控制器 Ch11

本书专注意味着:全书用 MVC 做网站(Part 1),用三种 Web 服务范式做 API(Part 2),用 Umbraco CMS 做内容管理(Part 3)。

第三层(架构本质):所有范式共享同一个 Microsoft.AspNetCore.App 框架,底层都是 Kestrel + Middleware Pipeline。这体现 .NET 设计的一个重要原则——"pay for what you use"(按需加载)——你可以从 Minimal API 起步,随复杂度增长逐步迁移到 MVC,而不需要更换框架。


概念卡片 4:MVC 设计模式在 ASP.NET Core 中的体现

属性 说明
概念名 MVC 设计模式 / Model-View-Controller
稳定性 稳定(经典模式,半个世纪历史)
全书追踪 Ch1 引入 → Ch2-8 全程使用

第一层(一句话直击本质):MVC 将 Web 应用分为三部分——Model(数据/业务)、View(表现层)、Controller(请求处理/协调)——实现关注点分离。

第二层(核心机制展开):

HTTP Request│▼
┌─────────────┐
│   Routing   │  URL → Controller::Action 映射
└─────┬───────┘▼
┌─────────────┐
│ Controller  │  1. 接收请求参数(Model Binding)
│             │  2. 调用业务逻辑(EF Core/Domain Service)
│             │  3. 选择 View 或返回数据
└─────┬───────┘│├──→ Model(数据传递:EF Core 实体 / ViewModel / DTO)│└──→ View(Razor .cshtml 渲染 HTML)│▼HTTP Response (HTML/JSON/XML...)

ASP.NET Core MVC 的核心程序集:Microsoft.AspNetCore.Mvc(包含 Controller 基类、[Route][HttpGet]IActionResult 等)。

第三层(架构本质):MVC 的本质是「Separation of Concerns(关注点分离)」在 Web 层的一次实现。Controller 是"交通指挥员"而非"搬运工"——它应该很"瘦",只做协调,不写业务逻辑。这也是为什么本书后续章节会引入 Repository Pattern、Service Layer 等设计模式来进一步分离关注点。


概念卡片 5:Razor 文件类型对比

属性 说明
概念名 Razor 文件类型 / Razor File Types
稳定性 稳定
全书追踪 Ch1 概述 → Ch2/4 深入(Razor Views/Tag Helpers)

第一层(一句话直击本质):Razor 是 ASP.NET Core 中嵌入 C# 代码的模板语法,分为 .cshtml(MVC/Razor Pages)和 .razor(Blazor 组件)两类。

第二层(核心机制展开):

文件扩展名 所属技术 关键指令 编译产物
.cshtml (MVC View) ASP.NET Core MVC @model @ViewBag @Html RazorView<TModel>
.cshtml (Razor Page) Razor Pages @page @model (PageModel) Page
.razor Blazor Component @code @rendermode ComponentBase
.cshtml (Partial) MVC Partial View @model — 无 Layout PartialViewResult
_ViewStart.cshtml MVC 设置 Layout / ViewData 全局默认 视图启动前执行
_ViewImports.cshtml MVC / Razor Pages 导入命名空间/Tag Helpers 全局配置 视图编译时注入

注意:.cshtml 的三重身份(MVC View, Razor Page, Partial View)由 @page 指令和 Controller/PageModel 的存在与否来区分。

第三层(架构本质):Razor 的底层是编译时解析而非运行时解释——所有 .cshtml 文件在编译期被转换为 C# 类(继承自 RazorPage<TModel>),因此性能优于解释型模板引擎。@ 符号是 C# 和 HTML 之间的上下文切换标记。


概念卡片 6:Content Management Systems (CMS) 与 Umbraco

属性 说明
概念名 Content Management System / Umbraco CMS
稳定性 稳定(Umbraco 已有 20+ 年历史)
全书追踪 Ch1 概述 → Ch13-14 完整实践

第一层(一句话直击本质):CMS 是让非技术人员也能管理网站内容的系统;Umbraco 是 .NET 生态中最流行的开源 CMS。

第二层(核心机制展开):

CMS 分类:

类型 代表 特点
Headless CMS Strapi, Contentful 仅提供内容 API,无前端渲染
Coupled CMS WordPress, Umbraco 内容管理 + 前端渲染一体化
Hybrid CMS Umbraco 14+ (Heartcore) 可 Headless 也可传统渲染

Umbraco 14 的重大变更:管理后台从前端框架 AngularJS 迁移到 Web Components (Lit + Vite),UI 更现代化,且原生支持 TypeScript。

第三层(架构本质):CMS 的本质是将「内容创建/编辑」与「内容存储/展示」解耦,并在中间插入「模板系统」。开发者定义内容类型(Document Types)和模板(Templates),内容编辑者填充内容。这其实也是一种 MVC——Document Type = Model,Template = View,Umbraco 内部路由 = Controller。


概念卡片 7:SPA 框架全景

属性 说明
概念名 SPA 框架 / Single Page Application Frameworks
稳定性 演进中(前端框架快速迭代)
全书追踪 Ch1 概述 → (本书以 MVC/Umbraco 为主,不展开 SPA)

第一层(一句话直击本质):SPA 框架将页面路由和渲染移至浏览器端,服务端只提供数据和 API,实现无刷新用户体验。

第二层(核心机制展开):

框架 语言 定位 本书关联
Blazor (WASM) C# .NET 原生 SPA,编译为 WebAssembly Ch1 提及
Angular TypeScript 企业级全功能 SPA Ch1 提及
React JavaScript/TS 组件化 UI 库(需搭配路由/状态管理) Ch1 提及
Vue JavaScript/TS 渐进式框架 Ch1 提及
Blazor Server C# 服务端渲染 + SignalR 连接 Ch1 提及

第三层(架构本质):SPA 改变了 Web 应用的计算边界——将无状态的 HTTP 请求/响应模型替换为有状态的客户端应用模型。优点是用户体验流畅、降低服务器负载;代价是 SEO 困难(需要 SSR/SSG 补救)、首屏加载慢、前端复杂度显著增加。这也是为什么本书选择 MVC + Umbraco 路线——成熟的服务器渲染在 SEO 和可维护性上仍有巨大优势。


概念卡片 8:Web 服务类型

属性 说明
概念名 Web 服务类型 / Service / Microservice / Nanoservice
稳定性 稳定(模式已定型)
全书追踪 Ch1 概述 → Ch9(Web API)→ Ch10(OData)→ Ch11(FastEndpoints)→ Ch12(集成测试)

第一层(一句话直击本质):Web Service 是面向网络的可编程接口;Microservice 是其细粒度独立部署版本;Nanoservice 进一步拆分到极致。

第二层(核心机制展开):

类型 粒度 部署单元 通信方式 数据管理
Service(服务) 粗(整个后端) 单进程/单容器 内部调用 共享数据库
Microservice(微服务) 细(单个业务领域) 独立容器 HTTP/gRPC/消息队列 每服务独立数据库
Nanoservice(纳米服务) 极细(单个函数) Serverless (Azure Functions/AWS Lambda) 事件触发 无状态或绑定存储

本书聚焦:传统 Web Service(Ch9 Web API),同时介绍 OData(Ch10)和 FastEndpoints(Ch11)作为替代方案。

第三层(架构本质):粒度选择的本质是「复杂度换灵活性」的权衡。Monolith → Service → Microservice → Nanoservice 每向右一步,运维复杂度指数级上升。.NET 的策略是"支持全谱系"——同一个 ASP.NET Core 框架可以构建所有粒度级别,你可以从 Controller 起步,需要时迁移到 FastEndpoints 或 Azure Functions。


概念卡片 9:项目结构策略

属性 说明
概念名 项目结构策略 / Project Structure Strategy
稳定性 演进中(VSA 仍在普及)
全书追踪 Ch1 概述 → Ch2-8(Technological Concerns 实践)→ Ch11(VSA 实践)

第一层(一句话直击本质):项目内部文件夹组织有两种对立策略——按技术分层(Controllers/Models/Views)和按业务功能(Features/Orders/Products)——后者即 Vertical Slice Architecture。

第二层(核心机制展开):

策略 文件夹示例 优点 缺点
Technological Concerns
(技术分层)
/Controllers/Models/Views/Services 一目了然,适合 MVC 教学 跨功能改代码需跳转多层
Feature Folders
(功能文件夹)
/Features/Orders//Features/Products/ 功能内聚,改一个功能只在一个目录 横切关注点(认证/日志)位置难定
Vertical Slice Architecture
(VSA)
/Features/Orders/ 内含 Controller+Handler+Model 自包含,高内聚低耦合 适合 FastEndpoints/MediatR 模式

本书的 MVC 项目(Ch2-8)主要使用 Technological Concerns 结构,FastEndpoints 项目(Ch11)使用 VSA 结构。

第三层(架构本质):文件夹结构的争论本质是"Cohesion vs. Discoverability"——技术分层的发现性好(你知道 Controllers 在哪),功能文件夹的内聚性好(改一个功能不跨目录)。真正的答案不是二选一,而是"在项目复杂度需要时"切换。本书作者的观点:对于学习型项目,技术分层策略更友好。


概念卡片 10:Central Package Management (CPM)

属性 说明
概念名 Central Package Management / CPM
稳定性 稳定(自 .NET 8 正式 GA)
全书追踪 Ch1 引入 → 全书所有项目使用

第一层(一句话直击本质):CPM 允许在解决方案级别用一个 Directory.Packages.props 文件统一管理所有项目的 NuGet 包版本,避免多项目中版本号漂移。

第二层(核心机制展开):

启用 CPM 的两步配置:

  1. 在 solution root 创建 Directory.Packages.props
<Project><PropertyGroup><ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally></PropertyGroup><ItemGroup><PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.0" /><PackageVersion Include="xunit" Version="2.9.2" /><!-- ... --></ItemGroup>
</Project>
  1. 每个项目的 .csproj 中 PackageReference 不再指定 Version:
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" />

全局开关也可以放在 Directory.Build.props 中。CPM 还支持:

  • VersionOverride:单个项目覆盖中央版本
  • GlobalPackageReference:跨所有项目的隐式包引用
  • .props 继承链:子目录可以有自己的 Directory.Packages.props 覆盖父级

第三层(架构本质):CPM 解决的是"多项目解决方案的版本治理"问题。它的对标方案是 npm 的 package.json(单一版本)、Maven 的 dependencyManagement(中央版本)。设计上,CPM 采用 opt-in(ManagePackageVersionsCentrally = true)而非强制,保证向后兼容。


概念卡片 11:Docker 容器化与 Azure SQL Edge

属性 说明
概念名 Docker 容器化 + Azure SQL Edge
稳定性 稳定
全书追踪 Ch1 搭建 → Ch8 深入(Aspire 容器编排)

第一层(一句话直击本质):用 Docker 运行 Azure SQL Edge 镜像获得一个可用的 SQL Server 实例,避免直接安装 SQL Server 的复杂配置。

第二层(核心机制展开):

完整操作流程:

# 1. 拉取镜像
docker pull mcr.microsoft.com/azure-sql-edge:latest# 2. 运行容器
docker run -d --name azuresqledge \-e "ACCEPT_EULA=Y" \-e "MSSQL_SA_PASSWORD=s3cret-Ninja" \-p 1433:1433 \mcr.microsoft.com/azure-sql-edge:latest# 3. 查看状态
docker ps -a# 4. 管理
docker start azuresqledge   # 启动
docker stop azuresqledge    # 停止
docker rm azuresqledge      # 删除容器
docker rm -f azuresqledge   # 强制删除(不用先停止)

关键概念:

概念 解释 示例
Image 只读模板,含操作系统 + 应用程序 mcr.microsoft.com/azure-sql-edge
Container Image 的运行实例 azuresqledge(命名容器)
Port Mapping 主机端口→容器端口 -p 1433:1433
Environment Variable 配置参数 ACCEPT_EULA, MSSQL_SA_PASSWORD
Docker Desktop Windows/macOS GUI 管理工具 含 Dashboard 和容器启停按钮

⚠️ 作者踩坑记录:Windows 11 上命令行 docker run 可能失败,建议通过 Docker Desktop GUI 操作。

第三层(架构本质):Docker 解决的根本问题是「环境一致性问题」——"在我机器上能跑"的终结者。Azure SQL Edge 是 SQL Server 的轻量级容器化版本,与完整 SQL Server 相比:不支持 SSIS/SSAS/SSRS、不支持表分区、不支持 FILESTREAM。但对于本书的 Northwind 学习场景完全够用。


概念卡片 12:EF Core Scaffold 与实体模型搭建

属性 说明
概念名 EF Core Scaffold / 数据库先行实体生成
稳定性 稳定
全书追踪 Ch1 基础搭建 → Ch3(CRUD 操作)→ Ch6(缓存仓库)

第一层(一句话直击本质):dotnet ef dbcontext scaffold 从现有数据库反向生成 C# 实体类 + DbContext,即 Database-First 开发方式。

第二层(核心机制展开):

完整流程(本书实战):

# 1. 安装 EF Core CLI 工具(全局)
dotnet tool install --global dotnet-ef# 2. 为 scaffold 目标项目添加 NuGet 包(Microsoft.EntityFrameworkCore.SqlServer + Design)# 3. 执行 scaffold(在 solution 根目录)
dotnet ef dbcontext scaffold \"Data Source=.;Initial Catalog=Northwind;Integrated Security=true;TrustServerCertificate=true;" \Microsoft.EntityFrameworkCore.SqlServer \--project Northwind.EntityModels \--context-dir . \--data-annotations \--namespace Northwind.EntityModels

核心参数:

参数 含义
连接字符串 SQL Server 连接信息(可用环境变量保护)
Provider Microsoft.EntityFrameworkCore.SqlServer
--project 目标类库项目
--context-dir DbContext 输出目录
--data-annotations 使用 [Table] [Column] 等 Data Annotations
--namespace 生成代码的命名空间

Scaffold 生成内容:

  • 实体类(Category.cs, Product.cs, Customer.cs ...)— 每张表一个类
  • NorthwindContext.cs — DbContext,含 DbSet<T>OnConfiguring/OnModelCreating
  • 导航属性(public virtual ICollection<Product> Products { get; set; }
  • Data Annotations([Key], [Column], [StringLength] ...)

第三层(架构本质):EF Core 的 Database-First vs Code-First 并非对立关系。Scaffold 的本质是「元数据提取 + 代码生成」——读取 SQL Server 的 INFORMATION_SCHEMA 系统视图,生成与表结构 1:1 映射的 POCO 类。这种模式的哲学是"让数据库结构成为 single source of truth",适合遗留系统集成和教学场景。


概念卡片 13:DI 服务生命周期

属性 说明
概念名 DI 服务生命周期 / Service Lifetimes
稳定性 稳定
全书追踪 Ch1 引入 → Ch8 深入(DI 容器深度使用)

第一层(一句话直击本质):ASP.NET Core 的 DI 容器提供三种服务生命周期——Transient(每次请求新实例)、Scoped(每个 HTTP 请求共享)、Singleton(整个应用生命周期共享)——以及 .NET 9 新增的 Keyed DI。

第二层(核心机制展开):

生命周期 注册方法 实例化时机 释放时机 典型用途
Transient AddTransient<T>() 每次注入 使用者释放 轻量级无状态服务
Scoped AddScoped<T>() 每个 HTTP 请求一次 请求结束 DbContext(EF Core 推荐)
Singleton AddSingleton<T>() 首次请求时(或启动时) 应用关闭 配置、缓存、日志
Keyed (.NET 9) AddKeyedScoped<T>(key) 按 key 路由 同对应生命周期 同一接口多实现切换

DbContext 生命周期陷阱:

  • AddTransient<NorthwindContext>() → 每次注入都新建,可能导致并发问题和内存浪费
  • AddScoped<NorthwindContext>() → 或 AddDbContext<T>(options, ServiceLifetime.Scoped)
  • AddSingleton<NorthwindContext>() → DbContext 不是线程安全的,不要这么做!

第三层(架构本质):DI 容器的本质是一个「类型注册表 + 对象工厂」。生命周期的核心差异在于「对象图的作用域边界」——Transient 无边界(每次都是孤岛),Scoped 边界是 HTTP 请求,Singleton 边界是整个进程。错误使用时最常见的问题:Captive Dependency——将一个 Scoped 服务注入到 Singleton 服务中,导致 Scoped 实例意外存活过原请求。


概念卡片 14:xUnit 单元测试

属性 说明
概念名 xUnit 单元测试框架
稳定性 稳定
全书追踪 Ch1 引入(验证实体模型)→ Ch7(Playwright UI 测试)→ Ch12(集成测试)

第一层(一句话直击本质):xUnit 是 .NET 生态中最广泛使用的单元测试框架,以 [Fact][Theory] 标注测试方法,支持并行执行。

第二层(核心机制展开):

xUnit vs NUnit vs MSTest:

特性 xUnit NUnit MSTest
测试方法标注 [Fact] / [Theory] [Test] / [TestCase] [TestMethod]
初始化/清理 Constructor + IDisposable [SetUp] / [TearDown] [TestInitialize] / [TestCleanup]
参数化测试 [Theory] + [InlineData] [TestCase] [DataRow]
并行执行 默认支持 需配置 需配置
断言风格 Assert.Equal(expected, actual) Assert.That(actual, Is.EqualTo(expected)) Assert.AreEqual(expected, actual)
包名 xunit NUnit MSTest.TestFramework

本书 xUnit 使用示例(验证实体模型):

using Northwind.EntityModels;namespace Northwind.EntityModels.Tests;public class NorthwindEntityTests
{[Fact]public void Category_Exists()  // 验证实体类可正常实例化{var category = new Category { CategoryName = "Test" };Assert.Equal("Test", category.CategoryName);}
}

第三层(架构本质):xUnit 的设计原则来自其命名——"Extreme Unit Testing"——每步操作是独立的(instance-per-test),不使用 [SetUp]/[TearDown] 而是靠构造函数和 IDisposable,这迫使测试之间零耦合。本书在 Ch1 就引入测试验证是一个重要信号——测试不是事后补丁,而是从第一章就伴随开发的实践。


概念卡片 15:连接字符串与敏感信息保护

属性 说明
概念名 连接字符串管理与敏感信息保护
稳定性 稳定
全书追踪 Ch1 引入 → 全书贯穿

第一层(一句话直击本质):连接字符串不应硬编码在代码中,尤其包含密码时,应通过环境变量或 Secret Manager 注入。

第二层(核心机制展开):

本书采用的环境变量策略:

// 在 OnConfiguring 中使用 SqlConnectionStringBuilder
string? user = Environment.GetEnvironmentVariable("MY_SQL_USR");
string? password = Environment.GetEnvironmentVariable("MY_SQL_PWD");SqlConnectionStringBuilder builder = new();
builder.DataSource = ".";           // 或 "(localdb)\\MSSQLLocalDB"
builder.InitialCatalog = "Northwind";
builder.IntegratedSecurity = false; // SQL Server 认证模式
builder.TrustServerCertificate = true;
builder.UserID = user;
builder.Password = password;
builder.MultipleActiveResultSets = true;
builder.ConnectTimeout = 3;
builder.Encrypt = true;
builder.PersistSecurityInfo = false;

环境变量设置方式:

平台 命令
Windows CMD setx MY_SQL_USR sa → 需重启终端
Windows PowerShell $env:MY_SQL_USR = "sa" → 当前会话
Linux/macOS export MY_SQL_USR=sa → 当前会话

第三层(架构本质):这体现了 Twelve-Factor App 的第三原则——"将配置存储在环境中"。代码和配置分离,环境(开发/测试/生产)切换时只需改环境变量,代码零变动。进阶方案包括 Azure Key Vault、Secret Manager (dev)、CI/CD 的加密变量。


概念卡片 16:NorthwindContext 扩展方法模式

属性 说明
概念名 NorthwindContext 扩展方法 / IServiceCollection Extension Pattern
稳定性 稳定
全书追踪 Ch1 定义 → Ch2-14 全部使用

第一层(一句话直击本质):AddNorthwindContext 是封装 DbContext 注册逻辑的 IServiceCollection 扩展方法,将复杂配置隐藏在方法内,对外暴露简洁接口。

第二层(核心机制展开):

namespace Northwind.DataContext;public static class NorthwindContextExtensions
{public static IServiceCollection AddNorthwindContext(this IServiceCollection services,string? connectionString = null){if (connectionString is null){// 使用环境变量 + SqlConnectionStringBuilder 构建连接字符串// ...(概念卡片 15 的代码)services.AddDbContext<NorthwindContext>(options =>options.UseSqlServer(builder.ConnectionString));}else{services.AddDbContext<NorthwindContext>(options =>options.UseSqlServer(connectionString));}return services;}
}

使用方式(Program.cs):

builder.Services.AddNorthwindContext();  // 一行注册,配置全部封装

第三层(架构本质):这是 .NET 生态中非常常见的「Builder Extension Pattern」。它的设计意图是:

  1. 降低认知负荷:消费者不需要了解 SqlConnectionStringBuilder 细节
  2. 封装变化:如果连接方式从 SQL Auth 变为 Managed Identity,只改这一处
  3. 可测试性:方法接受 connectionString 参数,测试时可以注入内存数据库的连接字符串

板块③:名词深度词典

# 名词 英文名 标准定义 所属概念卡片 类比理解 常见误解
1 ASP.NET Core ASP.NET Core 跨平台高性能的 .NET Web 框架,自 2016 年取代了仅 Windows 的 ASP.NET 卡片 1 就像 Django/Flask 之于 Python 以为 ASP.NET 和 ASP.NET Core 只是版本关系——实际是完整重写
2 Kestrel Kestrel ASP.NET Core 的内置跨平台 HTTP 服务器 卡片 2 Nginx 的 .NET 内置版 以为 Kestrel 直接暴露给 Internet 是安全的——生产环境前面需要反向代理
3 MVC Model-View-Controller 将应用分为数据/表现/控制三部分的设计模式 卡片 4 餐厅:菜单(Controller)→厨师(Model)→摆盘(View) 以为 Controller 应该写业务逻辑——它只做协调
4 Razor Razor Syntax ASP.NET Core 的 C#+HTML 混合模板引擎 卡片 5 ERB (Ruby)/Thymeleaf (Java) .cshtml 不只有一种用途——MVC View 和 Razor Page 都叫 .cshtml
5 Blazor Blazor 用 C# (而非 JavaScript) 构建交互式 Web UI 的框架 卡片 7 React 的 C# 版本 以为 Blazor 只能做 WebAssembly——还有 Blazor Server 模式
6 SPA Single Page Application 浏览器端路由 + 渲染的 Web 应用 卡片 7 桌面 App 搬到浏览器里 以为 SPA 天然优于传统渲染——SEO/首屏加载是硬伤
7 CMS Content Management System 内容管理系统 卡片 6 WordPress 的 .NET 版本 CMS 不等于 WordPress——Umbraco 有完全不同的架构理念
8 Umbraco Umbraco CMS .NET 生态中最流行的开源 CMS 卡片 6 Umbraco 是 "The Friendly CMS"——开源免费,但企业版需付费
9 Docker Docker 应用容器化平台 卡片 11 货柜标准化运输(集装箱) Docker 不是虚拟机——它共享宿主 OS 内核
10 Container 容器 Docker Image 的运行实例,隔离的轻量级运行时 卡片 11 程序运行在独立沙箱中 Container 不等于 Docker——Docker 只是最流行的容器引擎
11 Image Docker Image 只读模板,含完整运行环境 卡片 11 ISO 镜像文件 Image 不等于安装包——它是多层文件系统叠加
12 Port Mapping 端口映射 主机端口 ↔ 容器端口的转发 卡片 11 电话总机转接 端口映射 ≠ 网络桥接——映射只在 NAT 层
13 EF Core Entity Framework Core .NET 的轻量级对象关系映射 (ORM) 框架 卡片 12 Hibernate/SQLAlchemy EF Core 不是 EF 6.x 的简单升级——它从零重写
14 DbContext DbContext EF Core 中的数据库会话抽象,管理实体对象和数据库交互 卡片 12 JDBC Connection + ORM Session DbContext 不是线程安全的——多线程不要共享同一个实例
15 Scaffold 反向工程 从已有数据库生成实体类和 DbContext 卡片 12 3D 扫描实物生成 CAD 模型 Scaffold 不是一次性操作——数据库结构变化可重新执行
16 DI Dependency Injection 依赖注入,IoC 的一种实现方式 卡片 13 外卖送餐:不自己做,让容器送过来 DI 不是银弹——过度抽象会导致代码难以追踪
17 Transient 瞬态生命周期 每次注入返回新实例 卡片 13 一次性纸杯 不是"每次都创建"就一定安全——高频创建会增加 GC 压力
18 Scoped 作用域生命周期 每个 HTTP Request 内共享同一实例 卡片 13 会议室内共享白板 不是"每次请求都存活"就安全——不能在 Singleton 里引用 Scoped
19 Singleton 单例生命周期 整个应用生命周期内唯一实例 卡片 13 公司前台接待 Singleton 不是全局变量——它在 DI 容器管理下,可以 mock
20 CPM Central Package Management 在解决方案级别统一管理 NuGet 包版本 卡片 10 Maven 的 dependencyManagement CPM 不是必须的——标准版项目可以继续用 PackageReference Version
21 Data Annotation Data Annotations 用 C# 特性标注实体类的 ORM 映射规则 卡片 12 表单上的标签说明 Data Annotation 不等于 Fluent API——前者简单但灵活性差
22 Connection String 连接字符串 数据库连接所需的完整信息串 卡片 15 数据库的"门牌号+钥匙" 不需要 Integrated Security=true 同时提供 UserID/Password——它们是互斥的
23 SQL Edge Azure SQL Edge 适合边缘计算和本地开发的轻量级 SQL Server 卡片 11 SQL Server Express 的容器版 SQL Edge 不支持所有 SQL Server 功能(如 SSIS/SSAS)
24 xUnit xUnit.net .NET 的现代单元测试框架 卡片 14 pytest (Python)/JUnit (Java) [Fact] 用于无参测试,[Theory] 用于参数化测试——不可混用
25 Coverlet coverlet.collector xUnit 的代码覆盖率收集器 卡片 14 Istanbul/nyc (JS) 覆盖率 100% ≠ 代码没 bug——它只告诉哪些代码被执行过
26 VSA Vertical Slice Architecture 按业务功能垂直切分代码结构的架构模式 卡片 9 竖切蛋糕(每块都有奶油+蛋糕体) VSA 不是 Clean Architecture 的替代——是代码组织维度的补充
27 Tag Helper Tag Helpers 服务端渲染的 HTML 增强标签 卡片 5 Vue/React 的组件但运行在服务器 Tag Helper 不是 HTML Helper——前者像 HTML,后者是 C# 方法
28 GAC Global Assembly Cache .NET Framework 的全局程序集缓存 卡片 1 系统级的 lib 文件夹 .NET Core 不再使用 GAC——用 NuGet 缓存和共享框架
29 Minimal API Minimal API .NET 6 引入的极简 HTTP API 定义方式 卡片 3 Express.js/Flask 的 .NET 版 Minimal API 不是玩具——复杂场景可与 MVC 等价
30 SaaS Software as a Service 软件即服务,云端订阅模式 卡片 8 租房子而非买房子 SaaS ≠ 只是云部署——还含多租户/订阅计费/自动升级
31 Serverless 无服务器计算 开发者不管理服务器的云执行模型 卡片 8 共享单车(用即付费,不维护) Serverless ≠ 没有服务器——只是你不需要管
32 IIS Internet Information Services Microsoft 的 Web 服务器,ASP.NET Core 中退居反向代理角色 卡片 2 Apache httpd 的微软版本 IIS 在 Core 中不再"托管"应用——它转发请求给 Kestrel

板块④:概念→代码双向映射表

概念 对应的代码/类/方法 继承/实现关系 所在文件/位置
MVC 设计模式 Controller 基类 + IActionResult HomeController : Controller Ch2 Northwind.Mvc/Controllers/
MVC 设计模式 [Route("...")] [HttpGet] [HttpPost] Attribute, no inheritance Controller Action 方法上
Kestrel Web Server WebApplication.CreateBuilder(args)app.Run() Program.cs
CPM Directory.Packages.props MSBuild .props 继承链 Solution 根目录
CPM <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> MSBuild Property Directory.Packages.props
Docker 容器管理 docker pull / run / ps / stop / rm -f CLI 终端/命令提示符
EF Core Scaffold dotnet ef dbcontext scaffold <connStr> <provider> CLI 工具 终端(Solution 目录)
EF Core DbContext NorthwindContext : DbContext DbContextNorthwindContext Northwind.DataContext/
EF Core 实体 Category, Product, Customer 等 POCO 无继承(纯 POCO) Northwind.EntityModels/
EF Core 数据注解 [Table("Categories")] [Key] [Column] [StringLength] 特性类 实体类的属性上
EF Core 导航属性 public virtual ICollection<Product> Products { get; set; } Category 类中
DI Scoped 注册 services.AddDbContext<NorthwindContext>(options => ...) IServiceCollection 扩展 Program.cs / 扩展方法
DI 扩展方法模式 AddNorthwindContext(this IServiceCollection, string?) IServiceCollection 扩展方法 NorthwindContextExtensions.cs
连接字符串构建 SqlConnectionStringBuilder DbConnectionStringBuilderSqlConnectionStringBuilder NorthwindContextExtensions.cs
环境变量读取 Environment.GetEnvironmentVariable("MY_SQL_USR") System.Environment NorthwindContextExtensions.cs
xUnit 测试 [Fact] [Theory] [InlineData] xUnit 特性 Northwind.EntityModels.Tests/
xUnit 断言 Assert.Equal(expected, actual) Assert.NotNull(obj) xUnit Assert 静态类 测试方法内
项目引用 <ProjectReference Include="..." /> MSBuild Item .csproj 文件
razor Pages @page 指令 .cshtml 文件顶部

板块⑤:语法/API 深度速查表

API/方法 完整签名 参数详解 返回值 使用场景 ⚠️ 安全注意 ⚠️ 性能注意
AddDbContext<T> IServiceCollection AddDbContext<TContext>(Action<DbContextOptionsBuilder>, ServiceLifetime, ServiceLifetime) optionsAction: 配置数据库提供程序等;contextLifetime: 默认 Scoped;optionsLifetime: 默认 Singleton IServiceCollection (Fluent) 注册 EF Core DbContext(推荐方式) contextLifetime 注意选 Scoped(默认),选 Singleton 导致线程安全问题
UseSqlServer DbContextOptionsBuilder UseSqlServer(string, Action<SqlServerDbContextOptionsBuilder>?) connectionString: 连接字符串;optionsAction: SQL Server 特定配置(如重试策略) DbContextOptionsBuilder (Fluent) 指定 SQL Server 作为 EF Core 提供程序 连接字符串不可硬编码——用环境变量/Secret Manager 推荐 EnableRetryOnFailure() 配置重试策略
SqlConnectionStringBuilder SqlConnectionStringBuilder() 构造 + 属性设置 DataSource, InitialCatalog, UserID, Password, IntegratedSecurity, TrustServerCertificate, Encrypt, ConnectTimeout 对象,通过 .ConnectionString 获取 动态构建 SQL Server 连接字符串 PersistSecurityInfo=false 防止安全信息泄漏 ConnectTimeout=3 快速失败优于长时间挂起
Environment.GetEnvironmentVariable static string? GetEnvironmentVariable(string variable) variable: 环境变量名(区分大小写在 Linux) string? (未设置返回 null) 读取配置值 不检查 null 直接使用 → NullReferenceException
dotnet ef dbcontext scaffold CLI 命令:dotnet ef dbcontext scaffold <connStr> <provider> [options] connStr: 连接字符串;provider: Microsoft.EntityFrameworkCore.SqlServer--project:目标项目;--data-annotations:使用注解;--namespace:命名空间 生成实体类 + DbContext 文件 从已有数据库生成 EF Core 模型 连接字符串含密码时注意终端记录历史 大量表时生成可能很慢
docker run docker run [options] <image> -d: 后台运行;--name: 命名;-e: 环境变量;-p host:container: 端口映射 Container ID 创建并启动容器 -e 传密码会出现在 docker inspect 输出中 注意 -p 端口不与主机现有服务冲突
AddScoped<T> IServiceCollection AddScoped<TService>(Func<IServiceProvider, TService>?) 可选 factory delegate IServiceCollection (Fluent) 注册 Scoped 服务(每 HTTP 请求一份)
AddTransient<T> IServiceCollection AddTransient<TService>(Func<SP, TService>?) 可选 factory delegate IServiceCollection (Fluent) 注册瞬态服务(每次注入新实例) 高频率瞬态创建增加 GC 压力
AddSingleton<T> IServiceCollection AddSingleton<TService>(TService instance) 或 lambda 可选实例或 factory IServiceCollection (Fluent) 注册单例服务(全应用一份) 确保服务是线程安全的 单例持有大对象可能导致内存泄漏
[Fact] public void MethodName() { ... } 无参数 void / async Task 无参单元测试
[Theory] [Theory] [InlineData(a, b)] public void M(a, b) { ... } [InlineData] 提供多组参数 void / async Task 数据驱动测试(同逻辑多组数据)
Assert.Equal static void Equal<T>(T expected, T actual) expected: 期望值, actual: 实际值 void 断言两个值相等 对集合使用 Equal 比较引用而非内容——集合用 Assert.Equal(expected, actual, comparer)
[Table] [Table("TableName")] string name: 表名 自定义实体→表映射
[Key] [Key] 无参数 声明主键(非 Id/EntityName+Id 命名时需要)
AddNorthwindContext static IServiceCollection AddNorthwindContext(this IServiceCollection services, string? connectionString = null) services: DI 容器;connectionString: 可选显式连接字符串 IServiceCollection 一行注册 Northwind DbContext + 连接配置 null 时用环境变量构建→确保环境变量已在运行环境中设置

板块⑥:易混淆点对比台

对比组 1:Integrated Security=true vs User ID + Password

概念A 概念B 相同点 不同点
Integrated Security (Windows 认证) SQL Server 认证 (User ID/Password) 都是 SQL Server 的身份验证方式 Windows 认证用操作系统凭据,SQL 认证用独立的用户名/密码
- Data Source=.;Initial Catalog=Northwind;Integrated Security=true;
+ Data Source=.;Initial Catalog=Northwind;User ID=sa;Password=s3cret-Ninja;TrustServerCertificate=true;

选择建议:本地开发用 Integrated Security 更安全;Docker 容器(SQL Edge)不支持 Windows 认证,必须用 SQL 认证。


对比组 2:AddDbContext<T> vs AddScoped<T> 手动注册 DbContext

概念A 概念B 相同点
AddDbContext<T>(...) AddScoped<T>(sp => new T(...)) 都注册 Scoped DbContext
- services.AddDbContext<NorthwindContext>(options =>
-     options.UseSqlServer(connectionString));
+ services.AddScoped<NorthwindContext>(sp => {
+     var options = new DbContextOptionsBuilder<NorthwindContext>()
+         .UseSqlServer(connectionString).Options;
+     return new NorthwindContext(options);
+ });

选择建议:始终用 AddDbContext<T>——它正确处理 DbContextOptions 的 Singleton 生命周期和 DbContext 的 Scoped 生命周期,避免手动管理的陷阱。


对比组 3:MVC Controller vs Razor Page

概念A 概念B 相同点
MVC Controller (.cs + .cshtml) Razor Page (.cshtml + .cshtml.cs) 都能渲染 HTML 页面,都用 Razor 模板
# MVC 方式
- // HomeController.cs
- public IActionResult Index() { return View(); }
- // Views/Home/Index.cshtml  ← View 由 Controller 返回# Razor Pages 方式
+ // Pages/Index.cshtml.cs       ← PageModel 与 View 同目录
+ public class IndexModel : PageModel { ... }
+ // Pages/Index.cshtml           ← @page 指令使 .cshtml 可独立路由
维度 MVC Controller Razor Page
路由 基于 Controller/Action 约定或 [Route] 基于文件路径 + @page 指令
页面逻辑 在 Controller Action 中 在 PageModel 的 OnGet/OnPost 中
适用场景 复杂页面、多个相关 Action 简单 CRUD 页面
模型绑定 [FromBody] / 参数绑定 [BindProperty]

选择建议:如果需要多个相关的 GET/POST 操作共享同一个视图逻辑 → MVC Controller;如果是一个简单的表单页面 → Razor Page。


对比组 4:Scaffold --data-annotations vs Fluent API

概念A 概念B 相同点
Data Annotations ([Column] [Table]) Fluent API (modelBuilder.Entity<T>().ToTable()) 都定义实体→数据库映射规则
# Data Annotations 方式public class Category{
-     [Column("CategoryName", TypeName = "nvarchar(15)")]
+     [MaxLength(15)]public string CategoryName { get; set; }}# Fluent API 方式
+ modelBuilder.Entity<Category>(entity =>
+ {
+     entity.Property(e => e.CategoryName)
+           .HasMaxLength(15)
+           .HasColumnType("nvarchar(15)");
+ });
维度 Data Annotations Fluent API
配置位置 实体类上 OnModelCreating
可读性 高(配置靠近属性) 中(集中但长)
灵活性 低(有限的特性类) 高(完整配置能力)
注意点 实体类"污染" 实体类保持 POCO 纯净

选择建议:教学/简单项目用 Data Annotations(本书选择);复杂项目用 Fluent API(或混合使用——Fluent API 会覆盖 Data Annotations)。


对比组 5:docker stop + docker rm vs docker rm -f

概念A 概念B 相同点
docker stopdocker rm docker rm -f 都停止并删除容器
- docker stop azuresqledge
- docker rm azuresqledge
+ docker rm -f azuresqledge
维度 stop → rm rm -f
优雅关闭 是(SIGTERM → 10s wait → SIGKILL) 否(直接 SIGKILL)
速度 慢(等待优雅关闭) 快(立即强杀)
数据安全 较安全 可能丢失未写入磁盘的数据
适用场景 生产环境 开发环境/容器已出问题

选择建议:开发环境用 docker rm -f 更快;生产环境用 docker stop → docker rm 更安全。本书场景(SQL Edge 开发用)推荐 rm -f


对比组 6:.NET 8 (LTS) vs .NET 9 (STS)

概念A 概念B 相同点
.NET 8 (LTS) .NET 9 (STS) 共享相同的基础框架设计
# 安装不同
- winget install Microsoft.DotNet.SDK.8
+ winget install Microsoft.DotNet.SDK.9# 目标框架不同
- <TargetFramework>net8.0</TargetFramework>
+ <TargetFramework>net9.0</TargetFramework># .NET 9 新增 Keyed DI(.NET 8 不支持)
+ services.AddKeyedScoped<IMyService, MyServiceV1>("v1");
+ services.AddKeyedScoped<IMyService, MyServiceV2>("v2");
维度 .NET 8 (LTS) .NET 9 (STS)
支持周期 3 年(2023.11 → 2026.11) 18 月(2024.11 → 2026.5)
新特性 Keyed DI, HybridCache, 富文本日志
对比策略 更稳定,适合生产 更新,更多新特性
推荐场景 生产环境首选 学习/尝鲜/非关键应用

选择建议:本书同时标注两个版本兼容。学习建议用 .NET 9(体验最新特性),生产部署考虑 .NET 8 LTS。


板块⑦:显隐知识双轨清单

书中显性知识(白纸黑字写的)

  1. ASP.NET Core 从 2016 年 1.0 发展到 2024 年 .NET 9 的全部版本历史
  2. Classic ASP.NET 依赖 System.Web.dll(Win32 only),ASP.NET Core 不依赖
  3. Kestrel 是跨平台默认 Web 服务器,HTTP.sys 仅 Windows
  4. MVC / Razor Pages / Blazor / Web API / Minimal API 五类技术选项
  5. MVC 请求流程:Route → Controller → Model → View → Response
  6. CPM 通过 Directory.Packages.propsManagePackageVersionsCentrally 启用
  7. Docker 安装 Azure SQL Edge 的完整 docker run 命令
  8. dotnet ef dbcontext scaffold 从数据库生成实体类
  9. SqlConnectionStringBuilder 使用方法
  10. 环境变量 MY_SQL_USR / MY_SQL_PWD 保护敏感信息
  11. 三种服务生命周期(Transient / Scoped / Singleton)
  12. AddNorthwindContext 扩展方法模式
  13. xUnit [Fact][Theory] 基本用法
  14. .cshtml / .razor / @page 文件类型区分
  15. Umbraco 14 管理后台从 AngularJS 迁移到 Web Components
  16. SPA 四大框架(Blazor / Angular / React / Vue)概述
  17. Web Service / Microservice / Nanoservice 定义
  18. Tech Concerns vs Feature Folders vs VSA 项目结构对比
  19. docker ps -a 查看所有容器状态
  20. SQL 脚本 Northwind4AzureSqlEdgeDocker.sql 创建 Northwind 数据库

书中隐性知识(需推导才能理解的)

  1. DbContext 为什么必须是 Scoped? → 书中只说「应该」,未解释原因:每个 HTTP 请求需要独立的数据跟踪状态,请求之间不应共享 Change Tracker;且 DbContext 底层使用的 DbConnection 不支持并发操作
  2. 为什么用 SqlConnectionStringBuilder 而非拼接字符串? → 防止 SQL 注入不适用于连接字符串的场景,但拼接字符串容易出现转义错误、格式错误(如密码含 ;
  3. 环境变量方案 vs appsettings.json → 环境变量优先级更高(12-Factor App),appsettings.json 适合非敏感配置
  4. Scaffold 生成的是 Database-First 模型,为什么还需要手动修改? → 自动生成的代码不反映业务规则(如属性不是 nullable 但数据库列是 nullable → 手动加 #nullable disable 或用 ?
  5. --data-annotations 与 Fluent API 互补 → Data Annotations 不够表达复杂关系(如复合主键、级联删除策略),此时 OnModelCreating 中的 Fluent API 是唯一选择
  6. xUnit 为什么用 constructor + IDisposable 而不是 SetUp/TearDown? → 强制 instance-per-test 模式,避免测试间共享状态导致的非确定性测试(flake e tests)
  7. Docker port mapping 为什么用 1433:1433? → 主机 1433 是 SQL Server 默认端口,保持相同端口号方便工具连接;如果主机已占用(有本地 SQL Server),需改为如 14330:1433
  8. Coverlet 的 coverlet.collectordotnet test --collect:"XPlat Code Coverage" → 需要两个组件配合,collector 负责收集,dotnet test 命令负责触发

版本引发的潜在考点

  1. .NET Core 1.0 为什么从 1.0 开始而非 5.0?→ 因为是全新项目,不沿用 .NET Framework 4.x 版本号
  2. .NET Core 3.0 为什么是里程碑版本?→ 社区要求微软专注于 Core、放弃 .NET Framework(因此 3.1 成为很多企业的迁移版本)
  3. .NET 5 为什么跳过了 Core 4?→ 微软有 .NET Framework 4.x,避免版本号混淆
  4. .NET 8 引入 CPM 为正式特性(此前在 .NET 6/7 中为预览)
  5. .NET 9 新增 Keyed DI → 第一章尚未使用,但全书总览提到 Ch6/Ch8 会用到

章节测试预测

  1. 简答题:请描述 ASP.NET Core MVC 中一个 HTTP 请求的完整生命周期(从 Kestrel 收到请求到返回 HTML 响应)
  2. 简答题:解释 DotNet Core 1.0 → .NET 9 的版本演变路线及关键里程碑版本
  3. 操作题:用 Docker 启动一个 Azure SQL Edge 容器,然后执行 SQL 脚本创建 Northwind 数据库
  4. 操作题:使用 dotnet ef dbcontext scaffold 从 Northwind 数据库生成实体模型
  5. 概念辨析:对比 Transient / Scoped / Singleton 服务生命周期,及各自适用场景
  6. 编程题:编写 AddNorthwindContext 扩展方法,使用环境变量构建连接字符串
  7. 选择题:以下哪个不属于 ASP.NET Core 的 Web 服务器?A. Kestrel B. HTTP.sys C. IIS (in-process) D. Apache Tomcat

隐性概念捕获(v5.2)

  • Build-generated file path length trap:书中 Good Practice 提示 "clone to short path like C:\web-dev-net9"。这是 .NET 项目的常见陷阱——某些自动代码生成工具(如 Razor 编译)会产生超长文件路径(含多层嵌套 GUID 目录),超过 Windows 260 字符限制导致构建失败。
  • # in folder name trap:文件夹名中的 # 在某些构建工具链中被解释为特殊字符。如 C:\C# projects\ 会导致 MSBuild 解析错误。
  • Multiple Active Result Sets (MARS):MultipleActiveResultSets=true 允许在同一连接上同时执行多个查询。概念卡片 15 的连接字符串含此配置但未解释原因——Northwind EntityModels 的导航属性可能在序列化时触发同一连接上的嵌套查询。
  • ConnectTimeout = 3:默认 15 秒对于开发环境过长。3 秒快速失败是实战中的 DevOps 最佳实践(Fail Fast)。

板块⑧:本章知识织网图

图例

  • 依赖(必须先理解A才能理解B)
  • 配合使用(A和B常常一起出现)
  • 对比(A和B容易混淆)
  • 包含(A是B的组成部分)

本章内部织网图

                    ASP.NET Core 演进史 (卡片1)│├→ Kestrel Web Server (卡片2) ──── ⇢ ──── IIS / HTTP.sys│├──⊃── 技术选型全景 (卡片3)│         ││         ├→ MVC 设计模式 (卡片4) → Controller + Model + View│         ├→ Razor Pages ⇢ MVC│         ├→ Blazor WASM / Server ⇢ SPA 框架 (卡片7)│         ├→ Web API / Minimal API → Web Service (卡片8)│         └→ Umbraco CMS (卡片6) → Ch13-14│├──⊃── 项目结构 (卡片9)│         ││         ├→ Tech Concerns (本书 MVC 章使用)│         ├→ Feature Folders│         └→ VSA (Ch11 使用)│└──⊃── CPM (卡片10) ↔ Directory.Packages.props│└→ NuGet 版本统一管理(所有章节项目共用)Docker + SQL Edge (卡片11)│├→ docker pull → docker run → docker ps → docker rm -f│└→ 连接字符串 & 敏感信息 (卡片15)│├→ Environment.GetEnvironmentVariable├→ SqlConnectionStringBuilder└──→ EF Core Scaffold (卡片12)│├→ dotnet ef dbcontext scaffold├→ Entity 类 (Category, Product...)├→ NorthwindContext : DbContext├→ Data Annotations ([Table], [Key]...)│└──→ NorthwindContext 扩展方法 (卡片16)│└──→ DI 服务生命周期 (卡片13)│├→ Transient├→ Scoped ← DbContext (推荐)└→ SingletonxUnit 单元测试 (卡片14)│├→ [Fact] / [Theory]├→ Assert.Equal / NotNull├→ Coverlet 代码覆盖率└──→ 验证 实体模型 & DbContext (卡片12)

跨章节织网图

                              Ch1 (地基章)实体模型 · 环境搭建 · 技术全景│┌─────────────────────┼─────────────────────┐│                     │                     │▼                     ▼                     ▼┌───────────┐       ┌───────────┐        ┌───────────┐│ Part 1     │       │ Part 2     │        │ Part 3     ││ Ch2-8 MVC  │       │ Ch9-12 API │        │ Ch13-14    ││            │       │            │        │ Umbraco    ││ Ch2 MVC    │       │ Ch9 Web API│        │ CMS        ││ Ch3 EF     │       │ Ch10 OData │        │            ││ Ch4 UI     │       │ Ch11 Fast  │        └───────────┘│ Ch5 Auth   │       │ Endpoints  ││ Ch6 Cache  │       │ Ch12 集成   ││ Ch7 Test   │       │ 测试       ││ Ch8 Docker │       └───────────┘└───────────┘所有分支共享 Ch1 的:├── Northwind.EntityModels (实体类库)├── Northwind.DataContext (DbContext + 扩展方法)├── Directory.Packages.props (CPM 版本管理)└── Docker SQL Edge 数据库实例

跨章关键依赖:

  • Ch1 → Ch2:Ch2 直接引用 Northwind.EntityModelsNorthwind.DataContext,在 MVC Controller 中展示实体
  • Ch1 → Ch3:Ch3 在 Ch1 的 EntityModels 基础上进行 CRUD 操作和模型绑定
  • Ch1 → Ch9/10/11:三个 API 章节都引用 Ch1 的 Northwind EntityModels 作为数据源
  • Ch1 → Ch12:集成测试需要 Ch1 搭建的 Docker SQL Edge 环境
  • Ch8:深入 Ch1 引入的 Docker 概念,升级到 .NET Aspire 编排

http://www.jsqmd.com/news/968538/

相关文章:

  • FPGA异步接口毛刺问题:从“预知数据”错误到跨时钟域信号处理优化
  • VR-Video-Passthrough开源:VR180视频实时抠像+Alpha输出
  • 内行揭秘!2026武汉名表回收行情变局与变现真相 - 薛定谔的梨花猫
  • FitGirl游戏启动器终极指南:三步安装,轻松管理压缩游戏
  • 深入解析Cortex-M3内核:从架构原理到嵌入式开发实战
  • 3步终极实战指南:如何将Amlogic S9xxx电视盒子改造成高性能服务器
  • 从Protel 99 SE到现代EDA:电子设计入门、迁移与合法学习路径
  • 终极Unity Mod Manager完整指南:3步轻松管理游戏模组
  • 高效万能解压工具UniExtract2:技术深度解析与实战应用指南
  • 3分钟快速上手:用easy-topo轻松绘制专业网络拓扑图的完整指南
  • 上饶市婺源县餐饮住宿 婺源华联山庄 地址:江西省上饶市婺源县江湾镇晓起村菊红农庄南800米处 - 资讯纵览
  • 买商标哪家靠谱?2026选商标公司认准5大维度,正规平台全盘点 - 资讯纵览
  • 2026 黄山漏水维修攻略|苏易修缮:厨卫 / 阳台 / 外墙 / 屋顶 / 地下室|靠谱防水门店 - 苏易修缮
  • SRS 4.0 源码阅读笔记:从State Threads协程模型看高并发流媒体服务的设计哲学
  • 2026年武汉SCMP课程咨询入口怎么确认?众智商学院官网400和冯老师说明 - 众智商学院职业教育
  • 双屏异显时副屏横屏显示异常的修复方案:控件比例与文字压缩问题一站式解决
  • League Akari:英雄联盟玩家的智能游戏助手完整指南
  • RDMA 可靠连接下的 RNR 参数调优:从重试机制到连接崩溃的致命陷阱
  • Balena Etcher 终极指南:三步搞定系统镜像烧录的完整方案
  • 2026年长租性价比高的租车平台选哪家:供给层价格层保障层全维度评测 - 科技焦点
  • 2026年六西格玛绿带费用报名怎么核对?1580元质量管理课程咨询众智商学院官网400冯老师 - 众智商学院职业教育
  • 元器件分销商电商化转型:从B2B到品牌信任的生存之道
  • Oracle11g用exp导出空表失败?两种免改参数的实操补救方法
  • 2026 安庆漏水维修攻略|苏易修缮:厨卫 / 阳台 / 外墙 / 屋顶 / 地下室|靠谱防水门店 - 苏易修缮
  • 专业级贝塞尔曲线工具深度解析:Blender高级插件实战指南
  • 2026 福州高端翡翠回收行业深度报告 - 薛定谔的梨花猫
  • 3分钟解锁B站缓存视频:m4s-converter让你的珍贵收藏重获新生 [特殊字符]
  • zlib多平台预编译库包(含完整C源码、Makefile与CMake构建支持)
  • 如何在macOS上使用HSTracker:炉石传说卡组追踪器终极指南
  • Jsxer终极指南:5分钟掌握JSXBIN反编译技巧,让加密脚本重见天日