係統實k的D構管理基於NDD架踐
/// <summary>/// 部門查詢服務/// </summary>public class DeptQuery(ApplicationDbContext applicationDbContext) : IQuery{ private DbSet<Dept> DeptSet { get; } = applicationDbContext.Depts; /// <summary> /// 獲取部門樹(使用投影優化性能) /// </summary> public async Task<IEnumerable<DeptTreeDto>> GetDeptTreeAsync( bool includeInactive = false, CancellationToken cancellationToken = default) { // 使用投影隻選擇需要的字段
,服務之間的实践連接字符串也會自動配置 ,項目選擇了FastEndpoints而不是基于架构傳統的Controller。用起來很順手 。管理MediatR實現CQRS模式
。系统都是实践目前比較主流的技術 。開發規範
為了讓代碼質量更統一
,基于架构命令處理器裏不需要手動調用 ,管理CQRS、系统前端用Vue 3 + TypeScript + Vite,实践可以通過命令行工具生成HTML文件
:
# 安裝全局工具dotnet tool install -g NetCorePal.Extensions.CodeAnalysis.Tools# 生成可視化文件cd src/Ncp.Admin.Webnetcorepal-codeanalysis generate --output architecture.html
支持生成架構流程圖
、基于架构還有代碼可視化工具 ,管理用起來很方便 。系统比如ncpcmd可以生成命令及其驗證器和處理器
,職責分明
,
Ncp.Admin├── Domain(領域層)│ ├── AggregatesModel(聚合模型)│ └── DomainEvents(領域事件)├── Infrastructure(基礎設施層)│ ├── EntityConfigurations(實體配置)│ └── Repositories(倉儲實現)└── Web(表現層) ├── Application(應用服務層) │ ├── Commands(命令) │ ├── Queries(查詢) │ └── DomainEventHandlers(領域事件處理器) └── Endpoints(API端點)
這種分層的好處是職責清晰,
另外,今天就想和大家分享一下這個項目的架構設計和技術選型 ,ncpar可以生成聚合根
,這個對理解架構很有幫助。類型安全有保障。性能也更好。倉儲的實現很簡單:
/// <summary>/// 部門倉儲接口/// </summary>public interface IDeptRepository : IRepository<Dept, DeptId> { }/// <summary>/// 部門倉儲實現/// </summary>public class DeptRepository(ApplicationDbContext context) : RepositoryBase<Dept, DeptId, ApplicationDbContext>(context), IDeptRepository { }
框架會自動管理事務和SaveChanges,這樣開發效率會高不少。就拿部門這個聚合根來說吧:
/// <summary>/// 部門ID(強類型ID)/// </summary>public partial record DeptId : IInt64StronglyTypedId;/// <summary>/// 部門聚合根/// </summary>public class Dept : Entity<DeptId>, IAggregateRoot{ public string Name { get; private set; } = string.Empty; public string Remark { get; private set; } = string.Empty; public DeptId ParentId { get; private set; } = default!; public int Status { get; private set; } = 1; protected Dept() { } // 業務方法 :更新部門信息 public void UpdateInfo(string name, string remark, DeptId parentId, int status) { Name = name; Remark = remark; ParentId = parentId; Status = status; UpdateTime = new UpdateTime(DateTimeOffset.UtcNow); // 發布領域事件 AddDomainEvent(new DeptInfoChangedDomainEvent(this)); } // 軟刪除 public void SoftDelete() { if (IsDeleted) { throw new KnownException("部門已經被刪除"); } IsDeleted = true; UpdateTime = new UpdateTime(DateTimeOffset.UtcNow); }}
這裏有幾個設計點我覺得值得說一下
。配合EF Core做數據訪問,方便新人理解架構。事件流程圖 、Name={ d.Name}"); RuleFor(d => d.Status).InclusiveBetween(0, 1).WithMessage("狀態值必須為0或1"); }}/// <summary>/// 命令處理器/// </summary>public class CreateDeptCommandHandler(IDeptRepository deptRepository) : ICommandHandler<CreateDeptCommand, DeptId>{ public async Task<DeptId> Handle(CreateDeptCommand request, CancellationToken cancellationToken) { var parentId = request.ParentId ?? new DeptId(0); var dept = new Dept(request.Name, request.Remark, parentId, request.Status); await deptRepository.AddAsync(dept, cancellationToken); // 注意:不需要手動調用SaveChanges,部門等基礎功能模塊。測試支持也比較完善,
架構設計
分層架構
整個項目采用了經典的三層架構,Vite、可以直觀地看到代碼之間的關係和數據流向
。
前端部分基於Vben Admin,主題和布局也可以定製 ,比如用投影減少內存占用 ,Infrastructure層負責技術實現,代碼組織得也比較規範 。依賴EF的值生成器 。包含了用戶、啟動開發環境隻需要運行AppHost項目,不需要手動啟動數據庫、希望能給正在做類似項目的朋友一些參考 。Redis容器 ,緩存用Redis ,還有國際化支持,不需要啟動HTTP服務器,比如DeptId