Skip to content

为 DotNetGuideBlog 补齐可运行的分层 Article CRUD 示例并打通项目依赖链#1

Merged
YyUpDaily merged 2 commits into
mainfrom
copilot/fill-dotnet-guide-blog-architecture
Jun 2, 2026
Merged

为 DotNetGuideBlog 补齐可运行的分层 Article CRUD 示例并打通项目依赖链#1
YyUpDaily merged 2 commits into
mainfrom
copilot/fill-dotnet-guide-blog-architecture

Conversation

Copy link
Copy Markdown

Copilot AI commented May 31, 2026

DotNetGuideBlog 的 5 个分层项目此前是空壳且彼此无引用,导致分层无法协同。该 PR 按 WebAPI → BLL → Repository → DAL → Model 建立单向依赖,并补齐基于内存存储的 Article CRUD 示例,确保开箱可编译运行。

  • 项目依赖与包管理

    • 在各层 .csproj 中补充 ProjectReference,形成标准单向依赖链(并允许各层使用 Model)。
    • DotNetGuideBlogWebAPI 增加 Swashbuckle.AspNetCore 依赖,用于 Swagger。
  • Model 层:领域模型与契约

    • 新增 Entities/ArticleId/Title/Content/Author/CreateTime/UpdateTime/IsDeleted)。
    • 新增 Dtos/ArticleDtoCreateArticleRequestUpdateArticleRequest
    • 新增 Common/ApiResult<T>,统一 Success/Message/DataOk/Fail 工厂方法。
  • DAL 层:线程安全内存存储

    • 新增 IArticleDal / ArticleDal
    • 使用 ConcurrentDictionary<int, Article> + Interlocked 自增 ID 模拟数据库。
    • 提供异步 CRUD:GetListAsync/GetByIdAsync/AddAsync/UpdateAsync/DeleteAsync,删除采用软删除(IsDeleted)。
  • Repository 层:数据访问封装

    • 新增 IArticleRepository / ArticleRepository
    • 通过构造注入 IArticleDal,对 DAL 能力进行仓储封装并暴露统一接口。
  • BLL 层:业务编排与 DTO 映射

    • 新增 IArticleService / ArticleService
    • 编排仓储调用,处理实体与 DTO 转换。
    • 增加基础业务校验:标题不能为空、ID 非法或文章不存在时返回 false/null
  • WebAPI 层:REST 接口与启动配置

    • 新增 Controllers/ArticleControllerGET listGET by idPOSTPUTDELETE,统一返回 ApiResult<T>
    • 更新 Program.cs
      • IArticleDal/ArticleDal 注册为 Singleton(共享内存数据)
      • IArticleRepositoryIArticleService 注册为 Scoped
      • 开发环境启用 Swagger。
    • 移除默认模板示例:WeatherForecast.csWeatherForecastController.cs

示例(启动注入链):

builder.Services.AddSingleton<IArticleDal, ArticleDal>();
builder.Services.AddScoped<IArticleRepository, ArticleRepository>();
builder.Services.AddScoped<IArticleService, ArticleService>();
Original prompt

背景

YyUpDaily/FastFramework 是一款基于 .NET 8 的快速开发框架(fork 自 YSGStudyHards/FastFramework)。目前 Platforms/DotNetGuideBlog 平台已经创建了 5 个分层项目,但它们全部是空壳:

  • DotNetGuideBlogWebAPI(表现层):只有默认模板 Program.csWeatherForecast.cs,无实质逻辑
  • DotNetGuideBlogBLL(业务逻辑层):空项目
  • DotNetGuideBlogRepository(仓储层):空项目
  • DotNetGuideBlogDAL(数据访问层):空项目
  • DotNetGuideBlogModel(模型层):空项目

关键问题:从 FastFramework.sln 可以看出,这 5 个子项目之间没有任何 ProjectReference 依赖关系,各层是孤立的,无法协同工作。

所有项目均为 net8.0,并启用了 ImplicitUsingsNullable。WebAPI 项目使用 Microsoft.NET.Sdk.Web,其余使用 Microsoft.NET.Sdk

目标

请为 DotNetGuideBlog 平台填充一套标准、可编译运行的三层架构 CRUD 示例,以"博客文章(Article)"为业务实体,遵循项目现有命名风格(项目名 DotNetGuideBlog{层名},类用 XxxService/IXxxServiceXxxRepository/IXxxRepositoryXxxDal/IXxxDal 约定)。

具体要求

1. 建立各层项目引用(依赖链)

请在各 .csproj 中添加 ProjectReference,建立单向依赖:

  • DotNetGuideBlogModel:不引用任何项目
  • DotNetGuideBlogDAL:引用 Model
  • DotNetGuideBlogRepository:引用 DALModel
  • DotNetGuideBlogBLL:引用 RepositoryModel
  • DotNetGuideBlogWebAPI:引用 BLLModel

依赖方向:WebAPI → BLL → Repository → DAL → Model(所有层都可引用 Model)。

2. Model 层(DotNetGuideBlogModel)

  • Entities/Article.cs:博客文章实体(Id、Title、Content、Author、CreateTime、UpdateTime、IsDeleted 等字段)
  • Dtos/ArticleDto.cs:用于查询返回的数据传输对象
  • Dtos/CreateArticleRequest.csDtos/UpdateArticleRequest.cs:创建/更新的请求模型
  • Common/ApiResult.cs:通用返回结果包装类(含 Success、Message、Data,及 Ok/Fail 静态方法)

3. DAL 层(DotNetGuideBlogDAL)

  • 考虑到当前项目尚未引入 EF Core 或数据库,请使用**线程安全的内存数据存储(如 ConcurrentDictionary<int, Article> + Interlocked 自增Id)**来模拟数据库,避免引入数据库依赖导致无法编译运行。
  • 命名 IArticleDal / ArticleDal,提供 GetListAsyncGetByIdAsyncAddAsyncUpdateAsyncDeleteAsync(删除用软删除 IsDeleted)。

4. Repository 层(DotNetGuideBlogRepository)

  • IArticleRepository / ArticleRepository:通过构造函数注入 IArticleDal,封装对 DAL 的调用,提供 GetByIdAsyncGetListAsyncAddAsyncUpdateAsyncDeleteAsync

5. BLL 层(DotNetGuideBlogBLL)

  • IArticleService / ArticleService:通过构造函数注入 IArticleRepository,编排仓储调用,处理实体与 DTO 的转换,包含基本业务校验(如标题不能为空、文章不存在时返回 false/null)。

6. WebAPI 层(DotNetGuideBlogWebAPI)

  • Controllers/ArticleController.cs:提供 RESTful CRUD 接口(GET 列表、GET 单个、POST 创建、PUT 更新、DELETE 删除),统一返回 ApiResult<T>
  • 更新 Program.cs:注册依赖注入,IArticleDal/ArticleDal 注册为 Singleton(内存存储需共享数据),IArticleRepositoryIArticleService 注册为 Scoped;添加并启用 Swagger(开发环境)。
  • 删除默认的 WeatherForecast.cs 示例文件。
  • 为 WebAPI 的 csproj 添加 Swashbuckle.AspNetCore 包引用(用于 Swagger)。

验收标准

  • 整个解决方案能够编译通过(dotnet build 成功)。
  • 各层职责清晰、依赖方向正确(自上而下单向依赖)。
  • CRUD 接口可以通过 Swagger 或 HTTP 请求正常调用,数据能正确增删改查。
  • 代码遵循项目现有的命名规范和 net8.0 + ImplicitUsings + Nullable 风格。
  • 不破坏现有的 CoreShared 项目和解决方案结构。

注意事项

  • 使用内存存储模拟数据库,不要引入 EF Core、SQL Server 等需要外部数据库的依赖,确保开箱即可运行。
  • 保持代码简洁、注释清晰(中文注释,与项目风格一致),作为框架的示例代码供其他开发者参考。

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: .net ddd领域驱动分层标准,该怎么分层,每次该怎么命名,有什么作用,放什么东西

Assistant: # .NET DDD 领域驱动分层标准

DDD 经典分层是四层架构,在 .NET 中通常映射为多个项目(每层一个 .csproj)。下面给出业界主流的命名约定、职责和内容划分。


一、四层架构总览

┌─────────────────────────────────────┐
│  表现层 / API 层 (Presentation)        │  ← 用户/外部交互
├─────────────────────────────────────┤
│  应用层 (Application)                  │  ← 用例编排
├─────────────────────────────────────┤
│  领域层 (Domain)        ★核心★         │  ← 业务规则
├─────────────────────────────────────┤
│  基础设施层 (Infrastructure)           │  ← 技术实现
└─────────────────────────────────────┘

依赖方向(重点):所有层最终依赖 Domain,Domain 不依赖任何其他层。这就是 DDD 的核心原则——领域层保持纯净。


二、各层详解

1. Domain 层(领域层)★ 最核心

项目命名 YourApp.Domain

作用:承载所有核心业务逻辑和规则,与技术无关(不引用 EF Core、不引用 ASP.NET)。

放什么

YourApp.Domain/
├── Entities/            实体(有唯一标识,如 Order、User)
├── ValueObjects/        值对象(无标识,靠属性相等,如 Money、Address)
├── Aggregates/          聚合根(管理一组实体的一致性边界)
├── Enums/               领域枚举
├── Events/              领域事件(如 OrderPlacedEvent)
├── Exceptions/          领域异常(如 InsufficientStockException)
├── Repositories/        仓储【接口】(IOrderRepository,只定义不实现)
├── Services/            领域服务(跨实体的业务逻辑)
└── Specifications/      规约(封装查询/校验规则)

命名约定

  • 实体/聚合根:业务名词,OrderCustomer
  • 仓储接口:I + 聚合根 + RepositoryIOrderRepository
  • 领域事件:动作过去式 + EventOrderCancelledEvent
  • 领域异常:xxxException

2. Application 层(应用层)

项目命名 YourApp.Application

作用:编排业务用例(Use Case),协调领域对象完成一个完整操作。本身不含业务规则,只负责"流程指挥"。常配合 CQRS + MediatR

放什么

YourApp.Application/
├── Features/ (或 UseCases/)
│   └── Orders/
│       ├── Commands/        写操作(CreateOrderCommand + Handler)
│       └── Queries/         读操作(GetOrderByIdQuery + Handler)
├── DTOs/                    数据传输对象
├── Interfaces/              应用层接口(如 IEmailService、IUnitOfWork)
├── Mappings/               AutoMapper 映射配置
├── Behaviors/              MediatR 管道(验证、日志、事务)
└── Validators/             FluentValidation 校验器
```...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

Copilot AI changed the title [WIP] Add standard three-tier architecture to DotNetGuideBlog 为 DotNetGuideBlog 补齐可运行的分层 Article CRUD 示例并打通项目依赖链 May 31, 2026
Copilot AI requested a review from YyUpDaily May 31, 2026 16:53
@YyUpDaily YyUpDaily marked this pull request as ready for review June 2, 2026 01:01
@YyUpDaily YyUpDaily merged commit 9273cef into main Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants