NetCorePal Cloud Framework
概述
NetCorePal Cloud Framework 是一个基于 .NET 8 的企业级微服务开发框架,深度集成了领域驱动设计(DDD)和整洁架构(Clean Architecture)的最佳实践。该框架提供了完整的开发模板和工具库,帮助开发团队快速构建高质量的微服务应用。
核心特性
1. DDD 核心概念支持
- 聚合根与实体: 提供基础Entity类和IAggregateRoot接口
- 强类型ID: 支持IGuidStronglyTypedId和IInt64StronglyTypedId,避免ID类型混淆
- 领域事件: 内置IDomainEvent接口和事件发布机制
- 值对象: 支持值对象的定义和使用
- 仓储模式: 提供IRepository接口和RepositoryBase基类
2. CQRS 模式实现
- 命令处理: 基于MediatR的ICommand和ICommandHandler接口
- 查询处理: IQuery和IQueryHandler接口,支持读写分离
- 验证集成: FluentValidation自动验证支持
- 事务管理: 自动事务边界管理
3. 事件驱动架构
- 领域事件: 聚合内事件,事务边界内处理
- 集成事件: 跨服务事件,异步消息传递
- 事件处理器: 自动注册和调用机制
- 事件溯源: 可选的事件存储支持
4. 微服务基础设施
- 服务注册与发现: 支持Consul、Nacos等注册中心
- 配置管理: 集中式配置和动态刷新
- 链路追踪: OpenTelemetry集成
- 健康检查: 内置健康检查端点
- 熔断降级: Polly集成
5. 数据访问
- EF Core集成: 深度集成Entity Framework Core
- 多数据库支持: SQL Server、MySQL、PostgreSQL
- 自动审计: 创建时间、更新时间、操作人自动记录
- 软删除: 内置软删除支持
- 乐观并发: RowVersion自动管理
6. API开发
- FastEndpoints集成: 高性能端点路由
- 自动API文档: Swagger/OpenAPI支持
- 版本控制: API版本管理
- 响应包装: 统一响应格式
- 异常处理: 统一异常处理中间件
快速开始
1. 安装模板
2. 创建项目
# 创建新的微服务项目
dotnet new netcorepal-webapi -n MyProject
cd MyProject
# 恢复依赖
dotnet restore
# 运行项目
dotnet run --project src/MyProject.Web
3. 项目结构
MyProject/
├── src/
│ ├── MyProject.Domain/ # 领域层
│ │ ├── AggregatesModel/ # 聚合根
│ │ ├── DomainEvents/ # 领域事件
│ │ └── DomainServices/ # 领域服务
│ ├── MyProject.Infrastructure/ # 基础设施层
│ │ ├── Repositories/ # 仓储实现
│ │ ├── EntityConfigurations/ # 实体配置
│ │ ├── Migrations/ # 数据库迁移
│ │ └── ApplicationDbContext.cs
│ └── MyProject.Web/ # 表现层
│ ├── Application/ # 应用服务
│ │ ├── Commands/ # 命令
│ │ ├── Queries/ # 查询
│ │ ├── DomainEventHandlers/
│ │ └── IntegrationEvents/
│ ├── Endpoints/ # API端点
│ └── Program.cs
└── test/ # 测试项目
├── MyProject.Domain.UnitTests/
├── MyProject.Infrastructure.UnitTests/
└── MyProject.Web.UnitTests/
核心组件详解
强类型ID
框架提供了强类型ID支持,避免不同实体ID之间的混淆:
// 定义强类型ID
public partial record UserId : IGuidStronglyTypedId;
public partial record OrderId : IGuidStronglyTypedId;
// 使用强类型ID
public class User : Entity<UserId>, IAggregateRoot
{
protected User() { }
public User(string name)
{
Name = name;
// ID会由EF Core值生成器自动生成
}
public string Name { get; private set; } = string.Empty;
}
聚合根基类
public abstract class Entity<TId> where TId : notnull
{
public TId Id { get; protected set; } = default!;
private readonly List<IDomainEvent> _domainEvents = new();
protected void AddDomainEvent(IDomainEvent domainEvent)
{
_domainEvents.Add(domainEvent);
}
public IReadOnlyCollection<IDomainEvent> GetDomainEvents()
=> _domainEvents.AsReadOnly();
public void ClearDomainEvents()
=> _domainEvents.Clear();
}
public interface IAggregateRoot { }
仓储基类
public abstract class RepositoryBase<TEntity, TKey, TDbContext>
: IRepository<TEntity, TKey>
where TEntity : Entity<TKey>, IAggregateRoot
where TKey : notnull
where TDbContext : DbContext
{
protected readonly TDbContext Context;
protected RepositoryBase(TDbContext context)
{
Context = context;
}
public virtual async Task<TEntity?> GetAsync(
TKey id,
CancellationToken cancellationToken = default)
{
return await Context.Set<TEntity>()
.FindAsync(new object[] { id }, cancellationToken);
}
public virtual async Task<TEntity> AddAsync(
TEntity entity,
CancellationToken cancellationToken = default)
{
await Context.Set<TEntity>().AddAsync(entity, cancellationToken);
return entity;
}
// ... 更多默认方法
}
命令和查询接口
// 命令接口
public interface ICommand : IRequest { }
public interface ICommand<TResponse> : IRequest<TResponse> { }
// 命令处理器接口
public interface ICommandHandler<in TCommand> : IRequestHandler<TCommand>
where TCommand : ICommand { }
public interface ICommandHandler<in TCommand, TResponse>
: IRequestHandler<TCommand, TResponse>
where TCommand : ICommand<TResponse> { }
// 查询接口
public interface IQuery<TResponse> : IRequest<TResponse> { }
// 查询处理器接口
public interface IQueryHandler<in TQuery, TResponse>
: IRequestHandler<TQuery, TResponse>
where TQuery : IQuery<TResponse> { }
领域事件处理
// 领域事件接口
public interface IDomainEvent
{
DateTimeOffset OccurredOn { get; }
}
// 领域事件处理器接口
public interface IDomainEventHandler<in TDomainEvent>
where TDomainEvent : IDomainEvent
{
Task Handle(TDomainEvent domainEvent, CancellationToken cancellationToken);
}
配置与使用
Program.cs 配置
var builder = WebApplication.CreateBuilder(args);
// 添加服务
builder.Services
.AddFastEndpoints()
.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()))
.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly())
.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")))
.AddRepositories()
.AddDomainEventHandlers();
var app = builder.Build();
// 配置中间件
app.UseHttpsRedirection();
app.UseFastEndpoints();
app.Run();
数据库迁移
# 添加迁移
dotnet ef migrations add InitialCreate -p src/MyProject.Infrastructure -s src/MyProject.Web
# 更新数据库
dotnet ef database update -p src/MyProject.Infrastructure -s src/MyProject.Web
# 删除最后一次迁移
dotnet ef migrations remove -p src/MyProject.Infrastructure -s src/MyProject.Web
扩展方法
查询扩展
// WhereIf - 条件过滤
query.WhereIf(condition, x => x.Name == name)
// OrderByIf - 条件排序
query.OrderByIf(condition, x => x.CreateTime, descending)
// ToPagedDataAsync - 分页
await query.ToPagedDataAsync(pageIndex, pageSize, cancellationToken)
响应包装
// ResponseData<T> - 统一响应格式
public record ResponseData<T>
{
public bool Success { get; init; }
public T? Data { get; init; }
public string? Message { get; init; }
public int? ErrorCode { get; init; }
}
// 使用示例
return new ResponseData<UserId>
{
Success = true,
Data = userId,
Message = "用户创建成功"
};
最佳实践
1. 分层架构
- 严格遵守依赖方向:Web → Infrastructure → Domain
- Domain层保持纯净,不依赖外部框架
- 使用接口进行依赖倒置
2. 聚合设计
- 保持聚合边界小而清晰
- 通过聚合根访问和修改聚合内实体
- 使用强类型ID避免ID混淆
3. 命令和查询分离
- 命令用于修改状态,使用仓储
- 查询用于读取数据,直接用DbContext
- 避免在查询中修改状态
4. 事件驱动
- 在聚合内发布领域事件
- 使用领域事件处理器实现跨聚合协作
- 使用集成事件实现跨服务通信
5. 异常处理
- 使用KnownException处理业务异常
- 框架自动转换为合适的HTTP状态码
- 提供清晰的错误消息
性能优化
1. 查询优化
// 使用投影减少数据传输
var users = await context.Users
.Select(u => new UserDto(u.Id, u.Name, u.Email))
.ToListAsync();
// 避免N+1查询
var orders = await context.Orders
.Include(o => o.OrderItems)
.ToListAsync();
2. 缓存策略
// 使用IMemoryCache进行本地缓存
services.AddMemoryCache();
// 使用IDistributedCache进行分布式缓存
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
});
3. 异步编程
- 所有IO操作使用异步方法
- 正确传递CancellationToken
- 避免async void方法
常见问题
Q: 如何处理并发冲突?
A: 使用RowVersion属性实现乐观并发控制:
public class User : Entity<UserId>, IAggregateRoot
{
public RowVersion RowVersion { get; private set; } = new RowVersion(0);
// ...
}
// EF Core会自动检测并发冲突
Q: 如何实现软删除?
A: 添加IsDeleted属性并配置全局查询过滤器:
public class User : Entity<UserId>, IAggregateRoot
{
public bool IsDeleted { get; private set; }
public void Delete()
{
IsDeleted = true;
this.AddDomainEvent(new UserDeletedDomainEvent(this));
}
}
// 在DbContext中配置
modelBuilder.Entity<User>()
.HasQueryFilter(u => !u.IsDeleted);
Q: 如何处理长时间运行的操作?
A: 使用后台作业或消息队列:
// 使用Hangfire处理后台作业
services.AddHangfire(configuration => ...);
// 在命令处理器中触发后台作业
BackgroundJob.Enqueue(() => ProcessLongRunningTask(orderId));
相关资源
文档
示例项目
GitHub仓库
社区支持
- GitHub Issues: 报告问题和建议
- 讨论区: 技术交流和问题讨论
版本历史
v2.0.0 (2024-01)
- 升级到 .NET 8
- 改进强类型ID实现
- 增强事件处理机制
- 优化性能和内存使用
v1.5.0 (2023-11)
- 添加FastEndpoints集成
- 改进验证器自动注册
- 增强分页查询支持
v1.0.0 (2023-06)
- 初始版本发布
- 基础DDD支持
- CQRS模式实现
- 事件驱动架构
许可证
MIT License - 详见 LICENSE