From 9a0840c92aa4c3c58072e857f221e7db7e0e3b7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A5=9D=E6=84=8F=E8=BF=9C?= <15001284+du-yiyan@user.noreply.gitee.com> Date: Sun, 7 Jun 2026 14:48:41 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E7=A5=9D=E6=84=8F=E8=BF=9C29?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 祝意远 <15001284+du-yiyan@user.noreply.gitee.com> --- ...60601-AI\346\216\245\345\205\245vscode.md" | 78 ++++++++++++++++++ ...pi\347\232\204\345\210\233\345\273\272.md" | 26 ++++++ ...23\347\232\204\345\210\233\345\273\272.md" | 64 +++++++++++++++ ...46\215\256\345\272\223\347\232\204CRUD.md" | 81 +++++++++++++++++++ 4 files changed, 249 insertions(+) create mode 100644 "\347\245\235\346\204\217\350\277\234/20260601-AI\346\216\245\345\205\245vscode.md" create mode 100644 "\347\245\235\346\204\217\350\277\234/20260603-webapi\347\232\204\345\210\233\345\273\272.md" create mode 100644 "\347\245\235\346\204\217\350\277\234/20260604-webapi\347\232\204\346\225\260\346\215\256\345\272\223\347\232\204\345\210\233\345\273\272.md" create mode 100644 "\347\245\235\346\204\217\350\277\234/20260605-webapi\344\270\255\347\232\204\346\225\260\346\215\256\345\272\223\347\232\204CRUD.md" diff --git "a/\347\245\235\346\204\217\350\277\234/20260601-AI\346\216\245\345\205\245vscode.md" "b/\347\245\235\346\204\217\350\277\234/20260601-AI\346\216\245\345\205\245vscode.md" new file mode 100644 index 0000000..084aafe --- /dev/null +++ "b/\347\245\235\346\204\217\350\277\234/20260601-AI\346\216\245\345\205\245vscode.md" @@ -0,0 +1,78 @@ +# 笔记 + +在 VSCode 里接入 AI,就像给它安装了一个随时待命的编程搭档。最主流的方式,就是安装插件,让强大的 AI 模型能直接在编辑器中为你服务。 + +### 🧰 主流AI插件对比 + +下表整理了目前主流、各具特色的AI插件,你可以根据自己的需求快速选择。 + +| 插件名称 | 开发/支持方 | 核心特点 | 付费模式 | 适用场景 | +| :--- | :--- | :--- | :--- | :--- | +| **GitHub Copilot** | GitHub & OpenAI | 行业标杆,上下文理解强,支持多种主流语言。 | 付费订阅(有免费试用) | 希望获得最成熟、最智能化代码补全体验的开发者。 | +| **Codeium** | Codeium Inc. | **完全免费**,功能强大不输付费工具,支持超40种语言,响应快。 | 免费 | 个人开发者、学生或不想支付费用的用户。 | +| **通义灵码 (Tongyi Lingma)** | 阿里云 | **中文友好**,基于通义千问大模型,专为国内开发者优化。 | 免费 | 中文开发环境、国内团队协作。 | +| **Continue** | Continue Dev Team | **开源、高度可定制**,可灵活接入任意AI模型(如DeepSeek),支持本地模型。 | 开源免费 (API调用按模型计费) | 希望自由选择或切换模型,或对数据隐私有高要求的开发者。 | +| **Cline** | 第三方 | **全能型助手**,轻量级,支持多种LLM和MCP集成,上手快。 | 免费 (API调用按模型计费) | 希望在不改变现有工作流下引入AI的开发者。 | +| **RooCode** | 第三方 | 国内开发者友好,支持多模型切换,提供架构/编码/问答三种模式。 | 免费 (API调用按模型计费) | 需要灵活模型选择和模式切换的开发者。 | +| **Tabnine** | Tabnine | **自适应学习**,可学习个人编码风格,提供本地模型选项以保障代码隐私。 | Freemium (免费版有每日额度) | 注重代码隐私,或希望建议更贴合个人习惯的开发者。 | +| **Amazon Q** | Amazon Web Services (AWS) | **AWS开发专家**,为AWS服务提供专属代码补全和建议。 | 付费 (部分功能对AWS用户免费) | 主要使用AWS服务进行开发的团队或个人。 | +| **IntelliCode** | 微软 | **微软原生支持**,轻量级,资源占用小,基于上下文提供智能补全,完全免费。 | 免费 | 所有VSCode用户,尤其适合资源有限的开发环境。 | +| **Blackbox AI** | Blackbox AI | 内置代码片段库,可引用常见解决方案,安装简便。 | Freemium (免费版功能丰富) | 需要快速查找和使用代码示例的开发者。 | +| **CodeGPT** | CodeGPT | 将ChatGPT能力**直接集成到编辑器**,与AI深度对话。 | 免费 (需自备OpenAI API Key) | 熟悉OpenAI模型,需频繁进行复杂问题解答的开发者。 | +| **Bito** | Bito | 轻量级,提供全方位的AI辅助能力。 | Freemium | 追求轻量级解决方案的开发者。 | +| **TRAE** | 字节跳动 | 原名MarsCODE,支持国产模型。 | 待确认 | 偏好国内大模型和生态的开发者。 | +| **CodeBuddy** | 腾讯 | 轻量化设计,操作简单。 | 待确认 | 追求简单易用、快速上手的开发者。 | +| **Kilo** | 第三方 | 支持多种国外模型,新用户送20美元体验金。 | 有试用额度 | 希望体验国外先进模型的新用户。 | +| **CodeGeeX** | 智谱AI | 免费的VS Code插件,安装简单,对个人开发者无使用限制。 | 免费 | 寻求免费、易用替代方案的开发者。 | + +> **提示**:对于注重数据隐私的用户,可以优先考虑支持**本地运行模型**的插件,如 **Continue** 或 **Tabnine**,结合 **Ollama** 等工具。 + +### 🚀 如何接入:通用配置流程 + +无论选择哪款插件,接入流程都遵循相似的步骤: + +1. **插件安装** + * 打开 VSCode,点击左侧活动栏的“扩展”图标(或使用快捷键 `Ctrl+Shift+X` / `Cmd+Shift+X`)。 + * 在搜索框中输入插件名称(如 “Continue”)。 + * 点击 “Install”(安装)按钮即可。 + +2. **模型配置** + * **使用内置模型**:像 **GitHub Copilot** 这类插件,安装后**登录账号**即可使用。 + * **接入外部模型**:对于 **Continue** 这类插件,安装后需要在设置中填入对应 AI 服务商提供的 **API Key**。密钥通常可在 AI 服务商的官网控制台中获取。配置文件通常是 `config.json` 或 `config.yaml` 格式。 + * 以下是一个在 `config.json` 中配置多个模型的配置示例: + ```json + { + "models": [ + { + "name": "Pro/zai-org/GLM-4.7", + "provider": "siliconflow", + "model": "Pro/zai-org/GLM-4.7", + "apiKey": "您的_API_KEY" + }, + { + "name": "deepseek-ai/DeepSeek-V3.2", + "provider": "siliconflow", + "model": "deepseek-ai/DeepSeek-V3.2", + "apiKey": "您的_API_KEY" + } + ], + "tabAutocompleteModel": { + "name": "Qwen/Qwen3-Coder-480B-A35B-Instruct", + "provider": "siliconflow" + } + } + ``` + * **接入AI服务商**:除了直接使用API,还可以通过聚合平台(如**硅基流动 (SiliconFlow)**)接入多种模型,方便管理与切换。 + +### 🚦 接入后的典型用法 + +配置好插件后,它就可以在多种场景下发挥作用了: +* **🤖 智能代码补全**:在输入代码时提供上下文感知的补全建议,帮助你快速完成代码编写。 +* **🤖 自然语言编程**:通过自然语言描述功能需求,让 AI 直接生成代码,将想法快速变为现实。 +* **🤖 代码解释与调试**:选中不理解或出错的代码,让 AI 来解释其逻辑、找出潜在错误并修复。 +* **🤖 单元测试生成**:为指定的函数或类自动生成单元测试代码。 +* **🤖 代码重构与优化**:对现有代码提出改进建议,帮助提升代码质量和性能。 + + +# 作业 +无 \ No newline at end of file diff --git "a/\347\245\235\346\204\217\350\277\234/20260603-webapi\347\232\204\345\210\233\345\273\272.md" "b/\347\245\235\346\204\217\350\277\234/20260603-webapi\347\232\204\345\210\233\345\273\272.md" new file mode 100644 index 0000000..188aa8b --- /dev/null +++ "b/\347\245\235\346\204\217\350\277\234/20260603-webapi\347\232\204\345\210\233\345\273\272.md" @@ -0,0 +1,26 @@ +# 笔记 + +### 1. 创建项目 +- 使用 `dotnet new webapi -n MyShopApi --use-controllers` 创建名为 `MyShopApi` 的 Web API 项目。 +- `--use-controllers` 指定采用传统的 Controller 风格(而非 Minimal API)。 + +### 2. 运行项目 +- `dotnet run` 启动服务,默认监听 `http://localhost:5000` 和 `https://localhost:5001`。 +- 浏览器访问 `https://localhost:5001/swagger` 可看到默认的 `WeatherForecast` 接口。 +- 按 `Ctrl+C` 停止服务。 + +### 3. 关键文件与作用 +- **`Program.cs`**:应用入口。负责服务注册(DI)和中间件管道的配置(类似 Spring Boot 的配置类或 Express 的中间件)。 +- **`appsettings.json` / `appsettings.Development.json`**:配置文件,后者会覆盖前者(开发环境)。 +- **`MyShopApi.csproj`**:项目文件,定义目标框架、可空引用类型、隐式 using 等。 +- **`Controllers/`**:存放 Controller 的目录。 + +### 4. 清理示例 +- 直接删除 `Controllers/WeatherForecastController.cs` 即可(因为 .NET 8 模板中的 `WeatherForecast` 记录类内联在该文件中)。 + +### 实践步骤 +1. 执行创建命令 → 2. 运行并查看 Swagger → 3. 停止服务 → 4. 删除示例 Controller → 5. 重新运行(此时 Swagger 会报空,等待后续添加自己的 Controller)。 + + +# 作业 +无 \ No newline at end of file diff --git "a/\347\245\235\346\204\217\350\277\234/20260604-webapi\347\232\204\346\225\260\346\215\256\345\272\223\347\232\204\345\210\233\345\273\272.md" "b/\347\245\235\346\204\217\350\277\234/20260604-webapi\347\232\204\346\225\260\346\215\256\345\272\223\347\232\204\345\210\233\345\273\272.md" new file mode 100644 index 0000000..090bfd0 --- /dev/null +++ "b/\347\245\235\346\204\217\350\277\234/20260604-webapi\347\232\204\346\225\260\346\215\256\345\272\223\347\232\204\345\210\233\345\273\272.md" @@ -0,0 +1,64 @@ +# 笔记 + + +--- + +### 迁移的核心概念 +- **迁移 = 将 C# 实体模型的变化翻译成数据库 DDL 语句**(建表、改字段等)。 +- 类比 Git:`dotnet ef migrations add X` 类似 `git commit`,`dotnet ef database update` 类似 `git push`。 + +--- + +### 基本操作流程 + +| 步骤 | 命令 | 说明 | +|------|------|------| +| 1. 创建迁移 | `dotnet ef migrations add Init` | 生成 `Migrations/` 目录及迁移文件(含 `Up()` / `Down()`) | +| 2. 应用迁移 | `dotnet ef database update` | 在数据库中执行迁移,生成 SQLite 数据库文件(如 `myshop.db`) | +| 3. 验证 | SQLite Viewer 或 `dotnet ef dbcontext info` | 检查表结构是否创建成功 | + +--- + +### Seed 数据(预置初始数据) +- 在 `OnModelCreating` 中使用 `modelBuilder.Entity().HasData()` 配置。 +- **注意点**: + - 必须**手动指定主键 ID**(自增列在 Seed 时不会自动生成)。 + - 外键值必须对应已存在的分类 ID。 + - **修改 Seed 属于模型变更**,需要重新生成迁移并更新。 + +```csharp +modelBuilder.Entity().HasData( + new Category { Id = 1, Name = "电子产品", Description = "..." } +); +``` + +- 添加 Seed 后的操作: + ```bash + dotnet ef migrations add Seed # 生成新的迁移 + dotnet ef database update # 应用到数据库 + ``` + +--- + +### 常见问题与解决 + +| 问题 | 解决方法 | +|------|----------| +| `dotnet ef` 报错 Build failed | 先 `dotnet build` 看具体错误(检查 using、命名空间、DbContext 注册) | +| 迁移成功但数据库没变化 | 检查连接字符串路径是否正确(默认相对路径 `myshop.db`) | +| 修改实体后忘记生成迁移 | 养成习惯:修改模型后立即 `dotnet ef migrations add <描述>` | +| 修改 Seed 但数据库未更新 | 可删除 `.db` 文件后重新 `dotnet ef database update`(从零应用所有迁移) | + +--- + +### 实践要点 +1. 第一次迁移 `Init` → 生成空表。 +2. 通过 SQLite Viewer 确认表为空。 +3. 配置 `HasData` → 再次生成迁移 `Seed` 并更新 → 验证数据已插入。 +4. 建议每次模型变更都先读一下生成的迁移代码,确保与预期一致。 + +> 迁移是 EF Core 管理数据库版本演进的核心机制,Seed 让测试或演示环境拥有默认数据,两者结合可完整初始化数据库。 + + +# 作业 +无 \ No newline at end of file diff --git "a/\347\245\235\346\204\217\350\277\234/20260605-webapi\344\270\255\347\232\204\346\225\260\346\215\256\345\272\223\347\232\204CRUD.md" "b/\347\245\235\346\204\217\350\277\234/20260605-webapi\344\270\255\347\232\204\346\225\260\346\215\256\345\272\223\347\232\204CRUD.md" new file mode 100644 index 0000000..5bb1246 --- /dev/null +++ "b/\347\245\235\346\204\217\350\277\234/20260605-webapi\344\270\255\347\232\204\346\225\260\346\215\256\345\272\223\347\232\204CRUD.md" @@ -0,0 +1,81 @@ +# 笔记 + + + +--- + +### 1. 注入 DbContext +- 通过**构造函数注入**将 `AppDbContext` 传入 Controller。 +- DI 容器会在请求结束时自动释放 `DbContext`,无需手动 `Dispose`。 + +```csharp +public class CategoriesController : ControllerBase +{ + private readonly AppDbContext _db; + public CategoriesController(AppDbContext db) => _db = db; +} +``` + +--- + +### 2. 实现完整的 CRUD +以 `CategoriesController` 为例,所有方法均**异步**: + +| 方法 | 路由 | 操作 | 关键代码 | +|------|------|------|----------| +| `GetAll` | `GET /api/categories` | 查询所有 | `_db.Categories.ToListAsync()` | +| `GetById` | `GET /api/categories/{id}` | 按ID查找 | `_db.Categories.FindAsync(id)` | +| `Create` | `POST /api/categories` | 新增 | `_db.Categories.Add(input)` + `SaveChangesAsync()` | +| `Update` | `PUT /api/categories/{id}` | 修改 | 先 `FindAsync`,改属性,再 `SaveChangesAsync()` | +| `Delete` | `DELETE /api/categories/{id}` | 删除 | `_db.Categories.Remove(existing)` + `SaveChangesAsync()` | + +> `ProductsController` 按相同模式创建。 + +--- + +### 3. 关键机制 + +#### 异步操作 +- EF Core 所有数据库调用必须用 `Async` 后缀方法(`.ToListAsync()`、`.FindAsync()`、`.SaveChangesAsync()`),避免阻塞线程。 + +#### Change Tracking(变更追踪) +- 从数据库读出的实体**默认被跟踪**(`Find`、`FirstOrDefault`)。 +- 修改被跟踪实体的属性后,`SaveChangesAsync()` 会自动生成 `UPDATE` 语句。 +- 若使用 `.AsNoTracking()` 查询,需手动 `Update()` 才能生效。 + +#### Add / Remove +- `Add`:将实体标记为 `Added`,生成 `INSERT`。 +- `Remove`:标记为 `Deleted`,生成 `DELETE`。 + +--- + +### 4. 验证与测试 +1. 运行 `dotnet run`,打开 Swagger(`/swagger`)。 +2. 调用 `GET /api/categories` 应返回 Seed 中的 3 条数据。 +3. POST 新增一条商品,再 GET 验证数据已保存。 +4. 停止服务并重新启动,确认数据仍然存在(持久化成功)。 + +--- + +### 5. 常见坑与注意点 + +| 问题 | 原因 | 解决方案或说明 | +|------|------|----------------| +| 删除分类时报外键约束错误 | 分类下还有商品,`Restrict` 阻止删除 | 这是数据库层的兜底保护。第3章会改为友好的409响应。 | +| POST 时提示“Id is required” | 客户端漏传字段或模型绑定失败 | 下一章用 DTO + 验证解决。 | +| 修改 Seed 后数据未更新 | 迁移未重新应用 | 删除 `myshop.db`,重新 `dotnet ef database update`。 | +| POST 后立即 GET 看不到新数据 | Swagger 缓存或浏览器未刷新 | 刷新页面或直接访问 `/api/products`。 | +| `Update` 时某些字段未更新 | 遗漏了 `existing.X = input.X` 赋值 | EF 只更改被赋值的属性。下一章用 DTO 明确允许修改的字段。 | + +--- + +### 实践任务 +1. 改造 `CategoriesController` 为完整 CRUD。 +2. 新建 `ProductsController` 并实现相同方法。 +3. 通过 Swagger 测试所有接口,确认数据持久化。 +4. 尝试删除有商品的分类,观察外键约束错误(为第3章做准备)。 + +> 本节核心是**将 Controller 与真实的 DbContext 连接**,用异步 CRUD 操作数据库,并理解 EF Core 的变更追踪机制。 + +# 作业 +无 \ No newline at end of file -- Gitee From 10e4da95f4057c86a15eea4eb38f68e4fd20bf03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A5=9D=E6=84=8F=E8=BF=9C?= <15001284+du-yiyan@user.noreply.gitee.com> Date: Sun, 14 Jun 2026 07:09:58 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=E7=A5=9D=E6=84=8F=E8=BF=9C29?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 祝意远 <15001284+du-yiyan@user.noreply.gitee.com> --- ...26\351\224\256\345\205\263\347\263\273.md" | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 "\347\245\235\346\204\217\350\277\234/20260608-webapi\344\270\255\347\232\204\344\270\273\345\244\226\351\224\256\345\205\263\347\263\273.md" diff --git "a/\347\245\235\346\204\217\350\277\234/20260608-webapi\344\270\255\347\232\204\344\270\273\345\244\226\351\224\256\345\205\263\347\263\273.md" "b/\347\245\235\346\204\217\350\277\234/20260608-webapi\344\270\255\347\232\204\344\270\273\345\244\226\351\224\256\345\205\263\347\263\273.md" new file mode 100644 index 0000000..155cd8d --- /dev/null +++ "b/\347\245\235\346\204\217\350\277\234/20260608-webapi\344\270\255\347\232\204\344\270\273\345\244\226\351\224\256\345\205\263\347\263\273.md" @@ -0,0 +1,98 @@ +# 笔记 + +--- + +## 🧩 核心概念 + +| 概念 | 说明 | +|------|------| +| **一对多关系** | 一个实体(Category)对应多个另一个实体(Product) | +| **导航属性** | 实体间通过属性表达关系,而不是靠手动写 JOIN | +| **外键** | “多”端存储“一”端的主键值(如 `Product.CategoryId`) | + +--- + +## 🧱 实体配置模板 + +```csharp +// “一”端:Category +public ICollection Products { get; set; } + +// “多”端:Product +public int CategoryId { get; set; } +public Category? Category { get; set; } +``` + +**EF Core 约定识别规则**: +- 集合类型 → “一”端 +- 引用类型 → “多”端 +- `<类名>Id` → 外键 + +--- + +## ⚙️ `OnModelCreating` 显式配置(推荐) + +```csharp +modelBuilder.Entity() + .HasOne(p => p.Category) + .WithMany(c => c.Products) + .HasForeignKey(p => p.CategoryId) + .OnDelete(DeleteBehavior.Restrict); +``` + +### 🔁 方向解释 +- `HasOne` → Product 有一个 Category +- `WithMany` → Category 有多个 Product +- `Restrict` → 有子记录时禁止删除父记录 + +--- + +## 🧭 关系查询(必须 `Include`) + +```csharp +// 多 → 一 +await _db.Products.Include(p => p.Category).FirstAsync(); + +// 一 → 多 +await _db.Categories.Include(c => c.Products).FirstAsync(); +``` + +> ⚠️ **不写 `Include` → 导航属性为 `null`** + +--- + +## ❌ 常见踩坑点 + +| 问题 | 后果 | +|------|------| +| 忘记 `Include` | 导航属性为 null | +| 导航属性不是 `public` | EF Core 不识别 | +| 外键名不精确(如 `Categoryid` vs `CategoryId`) | 关系不成立 | +| `HasOne/WithMany` 配反 | 运行时关联错乱 | + +--- + +## ✅ 验证关系是否生效 + +1. **看 SQLite Viewer**:`Products` 表必须有 `CategoryId` 列 +2. **看迁移文件**:`Migrations/xxx_Init.cs` 中应有 + ```csharp + table.ForeignKey( + name: "FK_Products_Categories_CategoryId", + column: x => x.CategoryId, + principalTable: "Categories", + principalColumn: "Id", + onDelete: ReferentialAction.Restrict); + ``` + +> 🚫 **不要再执行** `dotnet ef migrations add AddRelationship` — 关系已在第 2 章存在,再生成会是空迁移。 + +--- + +## 📌 一句话总结 + +> **一对多关系 = 集合导航(一)+ 引用导航+外键(多),查询必带 `Include`,配置推荐 `OnModelCreating` 明确写法。** + + +# 作业 +无 -- Gitee