从这篇文章开始,咱们根据前面的DDD理论与DDD框架的约束,正式进入直销系统案例的开发。数据库
本篇文章主要讲产品上下文中的领域层的主要实现,先简单讲下业务方面的需求:产品SPU与产品SKU,产品SPU主要是产品的名字和相关描述,微信
产品SKU包括产品SPU的多个规格,每一个规格有不一样的价格与PV值。从咱们对DDD概念的理解,产品SPU与产品SKU属于同一个聚合,产品SPU是聚合根。框架
产品上下文主要实现产品的上架功能,为了实现上架功能,咱们首先要实现产品上下文的领域POCO模型与领域逻辑,ide
咱们将产品的POCO模型与领域逻辑创建到一个叫Product.Domain的项目中。工具
产品SPU领域对象POCO代码:ui
public partial class ProductSPU : IAggregationRoot { [Key] public Guid Id { get; set; } public string Code { get; set; } public string ProductSPUName { get; set; } public string ProductSPUDes { get; set; } public List<ProductSKU> ProductSKUS { get; set; } }
产品SKU领域对象POCO代码:this
public partial class ProductSKU : IEntity { public ProductSKU() { } [Key] public Guid Id { get; set; } public string Code { get; set; } public string Spec { get; set; } public Unit Unit { get; set; } public decimal PV { get; set; } public decimal DealerPrice { get; set; } public byte[] Image { get; set; } public Guid ProductSPUId { get; set; } public string ProductSPUName { get; set; } }
从上面代码能够看到,ProductSPU从聚合根接口继承,ProductSKU从实体接口继承,ProductSPU包含了一个ProductSKU的集合(也就是引用),这就表明它们同属一个聚合,在具体使用EF Core作spa
持久化时,会做为一个事务统一持久化。code
领域对象除了包含自身的属性,也应该包括自身的业务逻辑,产品上架的功能比较简单,业务逻辑也比较简单,主要就是如何生成整个领域对象,以及聚合根与实体业务标识符Code的生成规则。视频
产品SPU领域对象业务逻辑代码:
public partial class ProductSPU { public ProductSPU CreateProductSPU(Guid id,string spuname,string spudesc,List<ProductSKU> productskus) { this.Id = id; this.Code = "Code " + spuname; this.ProductSPUName = spuname; this.ProductSKUS = productskus; this.ProductSPUDes = spudesc; return this; } }
产品SKU领域对象业务逻辑代码:
public partial class ProductSKU { public ProductSKU CreateProductSKU(string productspuname,Guid productspuid, byte[] image,decimal dealerprice,decimal pv,string unit,string spec) { this.Id = Guid.NewGuid(); this.ProductSPUId = productspuid; this.Code = "Code " + productspuname + spec; this.ProductSPUName = productspuname; this.Image = image; this.DealerPrice = dealerprice; this.PV = pv; switch (unit) { case "盒": this.Unit = Unit.盒; break; case "包": this.Unit = Unit.包; break; case "瓶": this.Unit = Unit.瓶; break; } this.Spec = spec; return this; } }
我将领域对象的属性与领域对象的逻辑分到不一样的cs文件中,便于不一样职责人开发与管理,并且采用相同的名称空间和Partial关键字。
Product.Domain除了要实现领域逻辑以外,还要定义ProductSPU的仓储接口、经过EF Core定义产品上下文与数据库上下文之间的映射关系。
仓储接口定义:
public interface IProductRepository { void CreateProduct<T>(T productspu) where T : class, IAggregationRoot; }
从上面能够看到,这个接口其实就是定义了将ProductSPU这个聚合根持久化到数据库与的接口。
产品上下文与数据库上下文映射关系:
1.由于映射关系使用EF Core实现,将来可能被替换掉,因此先定义一个产品上下文接口:
public interface IProductContext { }
2.EF Core映射实现
public class ProductEFCoreContext:DbContext,IProductContext { public DbSet<ProductSPU> ProductSPU { get; set; } public DbSet<ProductSKU> ProductSKU { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionBuilder) { optionBuilder.UseSqlServer("数据库链接字符串"); } }
3.使用EF Core工具生成数据库脚本并更新数据库,在生成脚本时,须要编辑项目文件,并采用EF Core Tools命令生成,这里就不细讲EF Core技术方面的内容。
到这里,咱们就基本实现了产品上下文的领域层,能够看到领域层主要是领域逻辑,定义了一个仓储接口,将数据库技术解耦,固然要定义领域对象与数据库之间的映射关系,不然用例没法完成真正
对领域对象的持久化。
QQ讨论群:309287205
DDD实战进阶视频请关注微信公众号: