DDD实战进阶第一波(十二):开发一般业务的大健康行业直销系统(订单上下文POCO模型)
在本系列前面的文章中,我们主要讨论了产品上下文与经销商上下文相关的实现,大家对DDD的方法与架构已经有了初步的了解。
但是在这两个界限上下文中,业务逻辑很简单,也没有用到更多的值对象的内容。从这篇文章开始,我们来讲讲订单界限上下文实现的内容,里面的业务逻辑相对复杂一些,而且有大量值对象的引入来进行逻辑的处理。
订单上下文的需求主要是生成相应的订单项,每个订单项中有相关的订单产品和购买数量并生成订单项总额、订单项总PV,同时订单项总额和订单项总PV会累加到订单总额和订单总PV中,同时会根据订单总额扣减当前经销商的电子币,也会根据购买产品的PV,累加当前经销商的PV值。
1.订单界限上下文的领域模型:
从上图的领域模型中,大家可以看出订单是聚合根,订单明细是聚合的实体;订单聚合根总有总价、总PV、收获地址三个值对象,订单明细实体有明细总价、明细总PV、产品信息三个值对象。
2.明细总价值对象:
publicpartialclass OrderItemTotalPrice
{
publicdecimalSubTotalPrice {get;set; }
}
3.明细总PV值对象:
publicpartialclass OrderItemTotalPV
{
publicdecimalSubTotalPV {get;set; }
}
4.产品信息值对象:
publicpartialclass ProductSKUs
{
publicstringProductSPUName {get;set; }
publicdecimalProductPrice {get;set; }
publicdecimalProductPV {get;set; }
publicGuid ProductSKUId {get;set; }
}
5.订单明细实体:
publicpartialclass OrderItem : IEntity
{
publicstringCode {get;set; }
[Key]
publicGuid Id {get;set ; }
publicOrderItemTotalPrice OrderItemTotalPrice {get;set; }
publicOrderItemTotalPV OrderItemTotalPV {get;set; }
publicProductSKUs ProductSKUs {get;set; }
publicintCount {get;set; }
}
订单明细实体引入了OrderItemTotalPrice、OrderItemTotalPV、ProductSKUs三个值对象,同时具有自己的Code与Count两个属性。
6.订单总价对象:
publicpartialclass OrderTotalPrice
{
publicdecimalTotalPrice {get;set; }
}
7.订单总PV值对象:
publicpartialclass OrderTotalPV
{
publicdecimalTotalPV {get;set; }
}
8.订单收货地址值对象:
publicpartialclass OrderStreet
{
//省publicstringPrivince {get;set; }
//市publicstringCity {get;set; }
//区(县)publicstringZero {get;set; }
//街道地址publicstringStreet {get;set; }
}
9.订单聚合根:
publicpartialclass Orders : IAggregationRoot
{
publicstringCode {get;set ; }
[Key]
publicGuid Id {get;set; }
publicOrderStreet OrderStreet {get;set; }
publicOrderTotalPV OrderTotalPV {get;set; }
publicOrderTotalPrice OrderTotalPrice {get;set; }
publicDateTime OrderDateTime {get;set; }
publicGuid OrderDealerId {get;set; }
publicList OrderItems {get;set; }
publicstringTelephone {get;set; }
}
订单聚合根引入了OrderStreet、OrderTotalPV、OrderTotalPrice三个值对象;Code、DateTime(下单时间)、Telephone(联系电话)、OrderItems(订单项实体集)等几个属性。
10.生成数据库表:
根据前面文章的说明,我们可以依据上述POCO模型生成对应的数据库表,要注意的是,OrderItems可以自动识别为Orders的关联表,其他几个值对象我们要考虑是否是生成
单独的表还是作为相关实体或聚合根的表的列存在,一般情况下,我们是将这些值对象作为相关聚合根或实体表的列存在的。EF Core无法自动处理这些值对象如何存储到数据库中,
我们需要手工指定:
publicclass OrderEFCoreContext:DbContext,IOrderContext
{
publicDbSet Order {get;set; }
publicDbSet OrderItem {get;set; }
protectedoverridevoid OnConfiguring(DbContextOptionsBuilder optionBuilder)
{
optionBuilder.UseSqlServer("数据库连接字符串");
}
protectedoverridevoid OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity().OwnsOne(p => p.OrderStreet);
modelBuilder.Entity().OwnsOne(p => p.OrderTotalPrice);
modelBuilder.Entity().OwnsOne(p => p.OrderTotalPV);
modelBuilder.Entity().OwnsOne(p => p.OrderItemTotalPrice);
modelBuilder.Entity().OwnsOne(p => p.OrderItemTotalPV);
modelBuilder.Entity().OwnsOne(p => p.ProductSKUs);
}
从上面代码可以看出,在OnModelCreating时,可以指定6个值对象包含在对应的聚合根和实体相关的表中。
QQ讨论群:309287205
DDD实战进阶视频请关注微信公众号: