
这次我们来看一个和 .NET 后端开发强相关的完整实践项目.NET 10 Web API Full Course基于 Clean Architecture、EF Core并把 AI 能力Copilot Agent Gemini集成进业务接口。它不是那种只讲 CRUD 的入门 Demo而是把“企业级项目结构 数据访问 大模型能力接入”放在一条链路里跑通。如果你正准备用 .NET 接 AI 功能或者想把现有 API 项目从“能跑”重构到“能维护、能扩展”这篇文章可以直接收藏。先快速说清楚这个项目最核心的几条信息它围绕 .NET 10 的 Web API 模板展开用 Clean Architecture 做分层用 EF Core 做 ORM最后接入 AI Agent包含 Copilot Agent 和 Gemini作为业务能力。也就是说它覆盖了一条完整的后端开发主线项目分层、数据库实操、接口设计、AI 集成、单元测试与部署的常见思路。对 .NET 开发者的价值是“同一套代码里同时看到工程结构和 AI 对接”不是把 AI 单独拎出来做离线脚本。接下来我会带大家完整过一遍这类项目通常怎么落地先看核心能力与适用场景再走环境准备、部署启动、功能测试、API 调用与批量任务最后给出一套常见问题排查清单和工程化建议。文章中会给出可复制的命令、代码和配置模板但涉及具体路径、端口、模型名、API Key 的地方需要按你自己的项目环境替换——这一点非常重要因为 AI 服务的账号、地区和计费方式差异很大一篇博客没法替你做最终决策。1. 核心能力速览能力项说明项目类型.NET 10 Web API 全栈实践项目包含架构分层、数据库访问和 AI 集成核心架构Clean Architecture清晰架构典型分层为 Domain / Application / Infrastructure / Presentation数据访问EF Core支持迁移、仓储、查询与事务等常见数据库操作AI 能力接入 Copilot Agent 与 Gemini用于智能对话、内容生成、业务辅助等场景主要功能Web API 接口、数据库 CRUD、AI Agent 集成、单元测试、部署配置推荐运行环境Windows / Linux / macOS 均可以 .NET SDK 10 为前提硬件要求常规开发机即可AI 在线接口不需要本地 GPU如做本地模型则需另行确认显存启动方式dotnet run、Visual Studio 启动或命令行 publish 后运行API 能力提供标准 RESTful API可通过 Swagger / curl / Postman 调用批量任务可通过后台任务队列或定时服务实现项目默认更侧重接口维度适合读者.NET 后端开发、架构设计进阶者、想给业务接 AI Agent 的工程师需要说明的是AI Agent 在线版本不需要本地 GPU核心成本是模型 API 的调用费用如果未来替换成本地部署的大模型才需要考虑显存、推理框架和并发吞吐问题。表里没有给的参数比如具体接口地址、数据库连接串、模型版本、API Key 的获取方式都应该以你拉取的仓库 README 为准。原因在于 .NET 10 目前是较新的版本社区模板也在频繁更新硬编码某一个版本或端口反而不利于复现。2. 适用场景与使用边界这个项目适合三类人。第一类是从普通 Web API 往清晰架构迁移的 .NET 开发。很多项目一开始都是 Controller 里直接写业务逻辑时间一长就变成“上帝类”和“面条代码”。通过 Clean Architecture 分层可以明显感受到 Domain、Application、Infrastructure 的职责边界后续加功能、换数据库、写单元测试都会轻松很多。第二类是需要在 .NET 服务里接入 AI 能力的人。用 AI 不只有 Python 这条路。在 .NET 里通过 HTTP 调用大模型接口代码量不大关键是把 Prompt 管理、模型参数、结果解析抽象成独立服务。这个项目正好演示了 AI Agent 是如何作为 Infrastructure 或 Application 层的一个服务被注入到 API 中的。第三类是正在做技术选型或面试准备的人。Clean Architecture 的目录结构、EF Core 的 DbContext 设计、依赖注入的注册方式都是 .NET 面试里的高频考点。通过一个完整项目来理解比背八股文有效得多。边界也要说清楚。这类项目的主线是“在线 AI 接口接入”不是“本地大模型部署”。如果你追求的是完全离线、数据不出内网那么在线 Gemini 或 Copilot Agent 的默认方案并不满足要求。此时需要把 AI Provider 替换成内网模型服务同时确认数据合规策略。另外一个边界是版权与隐私。接入 AI Agent 时发送给模型的内容可能包含业务数据。在企业场景中要先确认这些数据是否可以发送给第三方 SaaS 服务。涉及用户隐私、商业机密、人脸或声音等敏感信息时必须做脱敏处理和数据流向审计。涉及版权素材、受保护文档内容时更要确认授权不能随意把文件丢给在线解析接口。简单说项目结构可以照搬AI 供应商要按业务合规要求选。3. 环境准备与前置条件先列一份通用环境清单不写死版本因为最新版本变化很快。建议以官方文档为准。操作系统Windows 10/11、Ubuntu 20.04、macOS 均可。.NET SDK需要 .NET 10 SDK。如果机器上同时装有多个版本用dotnet --list-sdks检查避免用错。数据库常见组合是 SQL Server LocalDB 或 PostgreSQL也可以换成 SQLite 快速验证。开发工具Visual Studio 2022、VS Code C# Dev Kit 或 Rider 都可以。Git拉取项目代码。网络环境需要能访问 NuGet 还原依赖包调用在线 AI 服务需要相应的网络连通条件。AI API Key如果要跑通 Gemini 或 Copilot Agent需要先准备好有效的密钥并确认账号有对应服务权限。安装与检查命令如下# 检查 .NET SDK 版本 dotnet --list-sdks # 检查运行时 dotnet --list-runtimes # 查看当前目录 ls # 拉取项目代码实际仓库地址以 README 为准 git clone https://github.com/your-repo/dotnet10-webapi-clean-architecture.git cd dotnet10-webapi-clean-architecture如果你只是想自己从零建一个类似结构的项目可以这样初始化dotnet new webapi -n CleanArchDemo dotnet new sln -n CleanArchDemo dotnet sln add CleanArchDemo/CleanArchDemo.csproj这一步不是必选项但能帮助你理解课程里“项目结构是逐步建出来”的思路。数据库方面常见做法是使用 Docker 启动一个 PostgreSQLdocker run --name clean-arch-db \ -e POSTGRES_USERadmin \ -e POSTGRES_PASSWORDadmin123 \ -e POSTGRES_DBcleanarch \ -p 5432:5432 \ -d postgres:16这是通用开发环境配置适合本地测试不要把默认密码直接带入生产环境。更稳妥的做法是使用环境变量或用户机密User Secrets管理连接串。4. 安装部署与启动方式这个项目不是“双击运行”的一键包而是标准 .NET 解决方案所以启动方式就按 .NET 项目最常规的流程来。4.1 还原依赖dotnet restore如果网络不好NuGet 还原失败常见的解决方法是换 NuGet 镜像源比如使用国内可用的 nuget 源。注意不要随便使用来历不明的第三方源。4.2 配置连接串和 AI 服务参数找到appsettings.Development.json把里面数据库连接字符串和 AI 服务相关配置替换成你自己的。示例结构如下{ ConnectionStrings: { DefaultConnection: Hostlocalhost;Port5432;Databasecleanarch;Usernameadmin;Passwordadmin123 }, AI: { Provider: Gemini, ApiKey: YOUR_API_KEY_HERE, Model: gemini-2.0-flash, Endpoint: https://generativelanguage.googleapis.com }, Logging: { LogLevel: { Default: Information } } }需要说明的是这里ApiKey只是配置模板实际请从环境变量或密钥管理服务读取不要提交到 Git 仓库。如果项目里用 OpenAI 兼容接口配置字段可能更接近baseUrl、apiKey、model。一切以项目 README 为准。4.3 执行 EF Core 迁移dotnet ef migrations add InitialCreate dotnet ef database update如果你还没有安装dotnet-ef工具先执行dotnet tool install --global dotnet-ef注意EF Core 迁移用的是启动项目的 DbContext如果你的解决方案里 DbContext 在 Infrastructure 层一定要确认StartupProject指向 API 项目。4.4 启动 Web APIdotnet run --project src/Presentation/CleanArch.Api默认情况下Kestrel 会监听http://localhost:5000或https://localhost:5001具体端口取决于launchSettings.json。启动后命令行会显示日志数据库迁移记录也会落到__EFMigrationsHistory表。打开 Swagger 页面通常是http://localhost:5000/swagger如果端口被占用可以显式指定dotnet run --project src/Presentation/CleanArch.Api --urls http://localhost:5100启动成功后会看到类似以下输出Now listening on: http://localhost:5100 Application started. Press CtrlC to shut down.到这一步一个不依赖任何外部工具的最小后端服务就已经跑起来了。5. 功能测试与效果验证下面按“API 基础能力 - 数据库操作 - AI Agent 能力”三个维度做验证。重点是学会判断某个功能到底是“成功”还是“失败”以及失败时从哪里排查。5.1 Web API 基础连通性测试先测试一个最简单的接口比如健康检查或天气接口。curl -X GET http://localhost:5000/api/health -H accept: application/json期望输出类似{ status: OK, timestamp: 2025-06-20T10:00:00Z }判断标准HTTP 状态码 200返回体是合法 JSON。如果连接被拒绝说明服务没有启动或端口不对如果返回 404说明路由前缀不同需要检查 Controller 路由。5.2 EF Core 数据写入与查询测试Clean Architecture 项目一般会有一个或多个业务实体。假设有一个Product实体名称、价格、库存那么它的写入接口和查询接口测试大致如下。创建产品curl -X POST http://localhost:5000/api/products \ -H Content-Type: application/json \ -d { name: Test Product, price: 99.9, stock: 10 }预期返回 201 Created响应体包含新记录的 Id。如果返回 400多半是参数校验不通过比如价格0。查询产品列表curl -X GET http://localhost:5000/api/products?pageIndex1pageSize10看到分页格式的 JSON 数组即成功。这里建议关注两点一是数据库是否真的落了数据可以用dotnet ef或数据库管理工具查看二是列表接口是否有分页分页可以避免一次查询数据量过大。5.3 EF Core 更新与删除测试更新操作通常使用PUT或PATCHcurl -X PUT http://localhost:5000/api/products/1 \ -H Content-Type: application/json \ -d { id: 1, name: Updated Product, price: 129.0, stock: 8 }如果返回 204 No Content 或 200 OK说明更新成功。如果返回 404说明 Id 不存在。删除操作curl -X DELETE http://localhost:5000/api/products/1返回 204 表示删除成功。删除后再次查询列表里不应再出现这条记录。5.4 Clean Architecture 分层验证代码分层是否真的“清晰”除了看目录还要关注依赖方向。一个常见的判断方法Domain 层不引用 Infrastructure。Application 层定义接口不引用 EF Core。Infrastructure 实现接口引用 EF Core 和 AI 服务。Presentation 层只做 HTTP 交互。用命令快速查看项目间的引用关系dotnet list reference或者查看某个项目引用了谁dotnet list src/Application/Application.csproj reference如果发现 Application 直接引用了 Microsoft.EntityFrameworkCore那说明分层已经“破功”了需要重构回去。这个验证步骤虽然不是功能测试但对长期维护很重要。5.5 AI Agent 功能测试AI Agent 是项目的另一个重点。假设有一个聊天接口POST /api/ai/chat请求体里包含用户消息和会话 Id。curl -X POST http://localhost:5000/api/ai/chat \ -H Content-Type: application/json \ -H Authorization: Bearer YOUR_API_KEY \ -d { sessionId: session-001, message: 请用一句话介绍 Clean Architecture, model: gemini-2.0-flash, temperature: 0.7 }预期返回{ reply: Clean Architecture 是一种通过分层和依赖规则让系统边界清晰、易于替换和测试的架构风格。, usage: { promptTokens: 32, completionTokens: 18 }, sessionId: session-001 }测试时要留意几个判断点是否返回正常 HTTP 200。返回内容是否与问题相关而不是固定话术。usage 字段是否存在这决定了你的 API 调用成本可观测性。如果带了会话 Id第二次提问时 AI 是否记得上下文。常见失败原因如下401API Key 无效或没有权限。429请求频率超限。500上游 AI 服务不可用或响应 JSON 解析失败。超时默认 HttpClient 超时太短需要调整为 60 秒或更长。5.6 智能总结或文档提取测试很多业务场景会用到“内容总结”。假设项目里有一个POST /api/ai/summarize接口接收一段长文本返回摘要。curl -X POST http://localhost:5000/api/ai/summarize \ -H Content-Type: application/json \ -d { text: 在这里贴入需要总结的长文本可以是一篇新闻、一份技术文档或商品评论。, maxLength: 200 }这个接口的价值在于它演示了如何把非结构化文本传给模型并让模型返回结构化结果。在真实业务中这一步通常就是“AI 接入业务系统”的最小闭环。如果项目里还涉及文档解析常见的做法是把 PDF、Word 或图片先转成文本再交给模型处理比如在 .NET 生态中可以使用 Aspose.Words 等库处理 Word 文档但这类商业库需要关注授权与许可证边界不能直接拿破解版或来路不明的组件用于生产。6. 接口 API 与批量任务6.1 API 接口设计Clean Architecture 下的 Web API 通常把路由前缀、请求/响应模型封装得很规范。一个典型的 Controller 结构如下[ApiController] [Route(api/[controller])] public class ProductsController : ControllerBase { private readonly IProductService _productService; public ProductsController(IProductService productService) { _productService productService; } [HttpGet] public async TaskActionResultPagedResultProductDto GetProducts( [FromQuery] int pageIndex 1, [FromQuery] int pageSize 20) { var result await _productService.GetPagedAsync(pageIndex, pageSize); return Ok(result); } }注意这里的 Controller 没有直接使用ProductDbContext而是依赖IProductService接口。这是 Clean Architecture 的一个核心特征API 层不关心数据来自 SQL Server 还是 PostgreSQL也不需要知道 AI 服务是 Gemini 还是 Copilot Agent。6.2 Python 调用示例如果你后续要做自动化测试、数据回填或定时任务用 Python 调用这个接口非常方便。示例import requests import json BASE_URL http://localhost:5000 # 1. 调用产品接口 def get_products(): resp requests.get( f{BASE_URL}/api/products, params{pageIndex: 1, pageSize: 10}, timeout30 ) resp.raise_for_status() return resp.json() # 2. 调用 AI 聊天接口 def chat_with_ai(message: str): payload { sessionId: auto-test-001, message: message, temperature: 0.3 } resp requests.post( f{BASE_URL}/api/ai/chat, jsonpayload, timeout120 ) resp.raise_for_status() return resp.json()[reply] if __name__ __main__: products get_products() print(products:, len(products.get(items, []))) reply chat_with_ai(请总结一下今天发布的文章) print(AI reply:, reply)设置timeout120是因为 AI 接口响应可能比普通 CRUD 慢得多。如果服务端做了流式输出SSE那么调用方式还要改成流式读取不能用一次性响应模型。6.3 批量任务的思路虽然这个项目主要演示接口但实际业务里 AI 集成经常需要批量处理。比如批量生成商品描述。批量审核文本合规性。批量提取 PDF 或 Word 中的关键字段。批量任务不建议直接在 Controller 的同步请求里跑因为这样会长时间占用连接。常见的做法是引入后台任务队列例如BackgroundService、ChannelT或 Hangfire把任务先写进队列工作进程逐个消费。一个最小化的BackgroundService思路public class AiSummarizeBackgroundService : BackgroundService { private readonly ILoggerAiSummarizeBackgroundService _logger; private readonly IServiceProvider _services; public AiSummarizeBackgroundService( ILoggerAiSummarizeBackgroundService logger, IServiceProvider services) { _logger logger; _services services; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { try { using var scope _services.CreateScope(); var queue scope.ServiceProvider.GetRequiredServiceITaskQueue(); var task await queue.DequeueAsync(stoppingToken); // 处理任务例如调用 AI 总结服务 await ProcessTaskAsync(task, stoppingToken); } catch (Exception ex) { _logger.LogError(ex, 批量任务处理失败); await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken); } } } private Task ProcessTaskAsync(object task, CancellationToken ct) { // 实际处理逻辑包括失败重试 return Task.CompletedTask; } }批量任务要重点考虑失败重试。AI 接口经常因为限流而失败所以重试策略要带上指数退避同时要给每个任务记录状态Pending / Processing / Completed / Failed否则失败后只能靠日志恢复。7. 资源占用与性能观察这个项目本身是 Web API本地开发时资源占用通常不高。打开任务管理器你会看到dotnet进程内存大约在 200-600MB 之间具体取决于是否加载了大型依赖、是否启用了热重载。如果你运行的是在线 AI 调用本地几乎不占用 GPU 显存因为计算发生在云端。不过有几个性能观察点值得大家留意。第一EF Core 查询性能。如果没有做分页直接ToListAsync()取出全部数据当表数据量大时接口会明显变慢。建议用分页查询并通过数据库索引优化常用字段。项目里如果出现“接口第一次请求很慢后续很快”有可能是 EF Core 模型冷启动或懒加载导致可以在日志里打开 EF Core 的 SQL 输出观察实际生成的 SQL。dotnet run --project src/Presentation/CleanArch.Api --environment Development在appsettings.Development.json中把 EF Core 日志级别调整为Information就能看到查询语句。第二AI 请求的延迟。调用在线模型通常需要 1-5 秒甚至更久这意味着你的 API 接口要有合理的超时配置。建议将 AI 相关接口的 HttpClient 超时设为 100 秒以上如果模型支持流式输出尽量用流式这样首字返回更快。第三并发控制。AI 接口通常有每分钟请求数限制Rate Limit。当你把接口并发压力变大时会触发 429。这时不应该简单调大并发而是要做令牌桶限流或请求排队。.NET 里可以用System.Threading.RateLimiting做简单的并发限制。第四docker 部署的资源占用。如果使用 Docker 部署 API加上 PostgreSQL 容器内存占用一般不会太高但如果把模型也跑在本地那就要单独去看 GPU 显存占用。编排建议API 和数据库可以放同一台机器AI 推理服务则根据模型大小单独规划。这里需要强调我并没有给出具体的“实测显存占用”因为在线 AI 服务的调用根本不占用本地显存如果你的团队选择本地模型显存占用会随模型参数、上下文长度和并发数变化必须用nvidia-smi实测。不要在博客里凭空断言某个模型一定占多少 G。8. 常见问题与排查方法问题现象可能原因排查方式解决方案dotnet restore失败NuGet 源连不上、版本冲突查看详细错误日志更换 NuGet 源、调整 PackageReference 版本运行dotnet ef提示命令不存在没有安装 dotnet-ef 工具dotnet tool list -g执行dotnet tool install --global dotnet-ef数据库迁移报“Connection refused”数据库没启动或连接串错用 psql/SSMS 手动连接测试检查数据库容器状态和连接串Web API 启动后端口被占用端口冲突看启动日志中的 bind 错误用--urls指定新端口Swagger 页面打不开服务未启动或路径不对确认控制台输出Now listening访问http://localhost:{port}/swaggerAI 接口返回 401API Key 无效检查 Key 是否多空格、是否在当前环境变量中读取重新配置环境变量重启服务AI 接口返回 429触发频率限制查看响应头和日志降低并发次数加指数退避重试AI 接口返回 500上游服务异常或模型名错误查看服务端日志、调用链确认模型名称是否存在、检查上游状态后台任务卡住队列消费逻辑异常看日志是否有死循环或超时加任务超时控制和失败重试输出内容不稳定温度参数过高或 Prompt 不稳定对比多次返回结果降低 temperature固定 Prompt 模板使用 Aspose.Words 等组件涉嫌破解使用未授权版检查许可证购买正版或替换为开源库注意授权边界下面把几个高频问题展开说明。NuGet 还原失败。这种情况多半是网络问题或包版本冲突。先看错误信息里提到哪个包再去 NuGet 官网确认该包是否存在、版本是否兼容。假如你本地装了多个 SDK可能出现“目标框架不一致”的报错需要用global.json固定 SDK 版本。EF Core 迁移失败。常见原因有两类一是连接串指向的数据库实例不存在二是多个项目交替迁移时 DbContext 找错。建议执行迁移时始终指定项目路径dotnet ef migrations add InitialCreate \ --project src/Infrastructure/Infrastructure.csproj \ --startup-project src/Presentation/CleanArch.Api.csprojAI 接口超时。不要以为加长 HttpClient 超时就能解决所有问题。如果上游接口真的不可用即使 120 秒超时也只会浪费时间。更稳妥的做法第一检查网络连通性第二用小请求测试模型名是否正确第三查看服务端日志中上游返回的状态码第四考虑用流式响应降低等待体验。端口冲突。在开发阶段经常遇到。# Windows 查看端口占用 netstat -ano | findstr :5000 # Linux 查看端口占用 ss -tlnp | grep 5000确认占用进程后可以关闭进程也可以直接给 API 换端口。9. 最佳实践与使用建议结合这个项目给出几组工程化建议。第一第一次先小参数测试。无论是 CRUD 还是 AI 接口先用最小输入跑通链路再加上复杂业务。比如先测试GET /api/health再测试 AI 聊天最后才做文档解析和批量任务。这样可以把“环境问题”和“业务代码问题”分开。第二保留一套最小可运行配置。在主项目之外维护一个包含最小 Controller、一个 EF Core Entity、一次 AI 调用的“骨架工程”这样后面引入新功能时可以先在骨架里试避免把主项目搞得一团糟。第三模型文件、输入素材、输出结果分目录管理。如果未来要扩展到本地模型一定要把模型权重、测试素材、输出目录分开用.gitignore忽略大文件和敏感数据。如果涉及大量文档解析原始 PDF/Word 文件、解析后的文本、AI 生成的摘要建议分三个目录方便回溯问题。第四批量任务要加日志和失败重试。AI 接口不是永远稳定。对每个任务记录状态、耗时、Token 消耗、模型版本和失败原因。在失败重试上采用“最多重试 3 次 指数退避”是比较通用的做法。第五接口服务要限制访问范围。不要把带 AI Key 的 API 直接暴露到公网至少要做身份认证和速率限制。AI Key 是成本敏感资源一旦被刷账单会很糟糕。开发环境可以限制只监听127.0.0.1生产环境必须放在网关后面。第六涉及人脸、声音、版权素材时必须确认授权。这个项目虽然是文本聊天与总结为主但如果你把 AI Agent 扩展成图片理解、语音合成或文档批量解析一定要注意数据来源和用途合法性。不能用爬虫抓取版权图片丢给模型不能未经授权处理含个人隐私的文档更不能使用破解版商业组件。第七发布或商用前要做效果复核。AI 生成的内容会有幻觉。面向用户输出前建议加一层“关键信息抽检”或人工审核。尤其在涉及健康、金融、法律等领域时AI 输出只能是辅助不能直接作为结论。第八关注依赖版本更新。.NET 10 和 EF Core 10 都还处在快速迭代期。建议使用 Dependabot 或 Renovate 定期升级依赖包升级后跑一遍集成测试避免“三个月后 NuGet 还原直接失败”的尴尬局面。10. 总结与下一步这个项目最值得尝试的一点是把 Clean Architecture、EF Core 和 AI Agent 集成放在同一个 .NET 10 Web API 工程里。你可以用一套代码同时看到“传统企业级后端工程”和“现代 AI 能力接入”的交叉点这对真实业务迁移非常有参考价值。拿到项目代码后最先应该验证的是dotnet run能不能正常启动Swagger 能不能打开接着跑一个 AI 聊天接口确认你的 API Key 和网络配置没问题最后再看 EF Core 迁移和 CRUD。最容易踩的坑集中在三个地方数据库连接串配错、AI Key 没有正确注入、启动项目指向错误导致迁移失败。后续可以继续扩展的方向也很明确把 AI 接口从聊天升级成“知识库问答”在 Application 层增加检索增强生成RAG把当前的单体 API 拆成模块化的垂直切片把 AI Agent 从在线接口换成内部私有化模型并补上完整的性能压测和成本监控围绕批量任务建立作业调度把每天的文档解析、摘要生成、内容审核做成无人值守流水线。如果你正在做 .NET 架构升级或准备把 AI 能力接入后端我建议先按文章里的验证步骤把这个项目完整跑一遍再决定哪些分层和抽象值得复制到自己的代码库。重复一遍所有涉及密钥、端口和模型名的地方都以你实际拉取的项目 README 为准。建议收藏备用等真正动手部署时再对照着排查。