该应用的领域很简单,有**Product**和**Category**两个实体以及一个**ProductStockState**枚举,如图所示:
![](https://img.kancloud.cn/18/13/1813193476712abfb7275e8dd4bdc076_1141x604.png)
实体在解决方案的领域层中定义,它分为两个项目:
* **.Domain**用于定义您的实体、值对象、领域服务、存储库接口和其他与领域相关的核心类。
* **.Domain.Shared**用于定义一些可用于其他层的共享类型。通常,我们在这里定义枚举和一些常量。
## 产品类别实体(Category)
`Category`实体用于对产品进行分类。*在ProductManagement.Domain*项目中创建一个*Categories*文件夹,并在其中创建一个`Category`类:
```
using System;
using Volo.Abp.Domain.Entities.Auditing;
namespace ProductManagement.Categories
{
public class Category : AuditedAggregateRoot<Guid>
{
public string Name { get; set; }
}
}
```
`Category`类派生自`AuditedAggregateRoot<Guid>`,这里`Guid`是实体的主键 (`Id`) 。您可以使用任何类型的主键(例如`int`、`long`或`string`)。
`AggregateRoot`是一种特殊的实体,用于创建聚合的根实体。它是一个**领域驱动设计**(**DDD**) 概念,我们将在接下来的章节中更详细地讨论。
相比`AggregateRoot`类,`AuditedAggregateRoot`添加了更多属性:`CreationTime`、、`CreatorId`、`LastModificationTime`和`LastModifierId`。
当您将实体插入数据库时,ABP 会自动给这些属性赋值,`CreationTime`会设置为当前时间,`CreatorId`会自动设置为当前用户的`Id`属性。
**关于充血领域模型**
在本章中,我们使用公共的 getter 和 setter 来保持实体的简单性。如果您想创建更丰富的领域模型并应用 DDD 原则和其他最佳实践,我们将在接下来的章节中讨论它们。
## 产品库存状态枚举(ProductStockState)
`ProductStockState`是一个简单的枚举,用来设置和跟踪产品库存。
我们在\*.Domain.Shared*项目中创建一个*Products\*文件夹和一个枚举`ProductStockState`:
```
namespace ProductManagement.Products
{
public enum ProductStockState : byte
{
PreOrder,
InStock,
NotAvailable,
Stopped
}
}
```
我们将在**数据传输对象(DTO)** 和界面层复用该枚举。
## 产品实体(Product)
在.Domain项目中创建一个*Products*文件夹,并在其中创建一个类`Product`:
```
using System;
using Volo.Abp.Domain.Entities.Auditing;
using ProductManagement.Categories;
namespace ProductManagement.Products
{
public class Product : FullAuditedAggregateRoot<Guid>
{
public Category Category { get; set; }
public Guid CategoryId { get; set; }
public string Name { get; set; }
public float Price { get; set; }
public bool IsFreeCargo { get; set; }
public DateTime ReleaseDate { get; set; }
public ProductStockState StockState { get; set; }
}
}
```
这一次,我继承自`FullAuditedAggregateRoot`,相比`Category`d的`AuditedAggregateRoot`类,它还增加了`IsDeleted`、`DeletionTime`和`DeleterId`属性。
`FullAuditedAggregateRoot`实现了`ISoftDelete`接口,用于实体的**软删除**。即它永远不会从数据库中做物理删除,而只是标记为已删除。ABP 会自动处理所有的软删除逻辑。包括下次查询时,已删除的实体会被自动过滤,除非您有意请求它们,否则它不会在查询结果中显示。
>[success] 注:数据过滤系统详情将在\[*第 8 章*\] 进行深入介绍。
## 导航属性
在这个例子中,`Product.Category`是一个导航属性为`Category`的实体。如果您使用 MongoDB 或想要真正实现 DDD,则不应将导航属性添加到其他聚合中。但是,对于关系数据库,它可以完美运行并为我们的代码提供灵活性。
解决方案中的新文件如图所示:
![](https://img.kancloud.cn/d9/61/d9612e3f89845452ddd70682abd3c252_512x666.png)
我们已经创建了领域对象。接下来是常量值。
## 常量值
这些常量将在输入验证和数据库映射阶段进行使用。
首先,在.Domain.Shared项目中创建一个 *Categories* 文件夹并在里面添加一个类`CategoryConsts`:
```
namespace ProductManagement.Categories
{
public static class CategoryConsts
{
public const int MaxNameLength = 128;
}
}
```
在这里,`MaxNameLength`值将用于`Category`的`Name`属性的约束。
然后,在.Domain.Shard的 *Products* 文件夹中创建一个`ProductConsts`类:
```
namespace ProductManagement.Products
{
public static class ProductConsts
{
public const int MaxNameLength = 128;
}
}
```
该`MaxNameLength`值将用于约束`Product`的`Name`属性。
![](https://img.kancloud.cn/89/58/89588d0ff4f4ba2f7ae7b1648279b044_246x165.png)
现在,领域层已经完成定义,接下来将为 EF Core 配置数据库映射。
- 前言
- 第一部分
- 第1章 现代软件开发和 ABP 框架
- 企业级 Web 开发的挑战
- ABP框架的能力清单
- 第2章 ABP框架入门
- 安装 ABP CLI
- 创建新解决方案
- 运行解决方案
- 探索预构建模块
- 第3章 逐步开发开发ABP应用
- 创建解决方案
- 定义领域对象
- EFCore和数据库映射
- 定义应用服务
- 测试产品
- 产品列表
- 创建产品
- 编辑产品
- 删除产品
- 第4章 探索 EventHub解决方案
- 应用介绍
- 架构探索
- 方案运行
- 第二部分
- 第5章 探索ABP基础架构
- 了解模块化
- 使用依赖注入系统
- 配置应用程序
- 实现选项模式
- 日志系统
- 第6章 数据访问基础架构
- 定义实体
- 定义仓储库
- EF Core集成
- 了解 UoW
- 第7章 探索横切关注点
- 认证授权
- 用户验证
- 异常处理
- 第8章 体验 ABP 的功能和服务
- 获取当前用户
- 使用数据过滤
- 控制审计日志
- 缓存数据
- 本地化用户界面
- 第三部分
- 第9章 理解领域驱动设计
- 介绍 DDD
- 构建基于 DDD 的 解决方案
- 处理多个应用程序
- 了解执行流程
- DDD的通用原则
- 第10章 领域层 Domain
- 领域事件案例分析
- 聚合和实体的设计原则和实践
- 实现领域服务
- 落地存储库
- 构建规约(Specification)
- 领域事件
- 第11章 应用层 Application
- 落地应用服务
- 设计 DTO
- 理解各层的职责
- 第四部分
- 第12章 MVC/Razor 页面
- 主题系统
- 绑定和压缩
- 导航菜单
- Bootstrap标签助手
- 创建表单并验证
- 使用模态窗口
- 使用JS API
- 调用HTTP API
- 第13章 Blazor WebAssembly UI
- 什么是Blazor
- ABP Blazor UI
- 验证用户身份
- 理解主题系统
- 使用菜单
- 使用基本服务
- 使用UI服务
- 消费HTTP API
- 使用全局脚本和样式
- 第14章 HTTP API 和实时服务
- 构建HTTP API
- 使用HTTP API
- 使用SignalR
- 第五部分
- 第15章 落地模块化
- 理解模块化
- 构建支付模块
- 安装模块
- 第16章 实现多租户
- 理解多租户
- 多租户基础设施
- 使用功能系统
- 何时使用多租户
- 第17章 构建自动化测试
- 了解ABP测试基础设施
- 构建单元测试
- 构建集成测试