领域驱动设计DDD实战进阶第一波(六):开发通常业务的大健康行业直销系统(实现产品上下文仓储与应用服务层)

前一篇文章咱们完成了产品上下文的领域层,咱们已经有了关于产品方面的简单领域逻辑,咱们接着来实现产品上下文关于仓储持久化与应用层的用例如何来协调领域逻辑与仓储持久化。前端

首先你们须要明确的是,产品上下文的领域逻辑是系统的核心,它不该该依赖仓储,而仓储应该要依赖领域层,这样仓储才能够把领域逻辑执行完后,才可能将领域对象持久化到数据库中,这一点与传统的架构有本质的区别。数据库

通常咱们会在解决方案中创建一个项目,这个项目就是包含了全部聚合的仓储实现,具体不一样上下文的仓储实现,能够在这个项目下创建不一样的文件夹。微信

1.产品上下文仓储实现:

public class ProductEFCoreRepository : IProductRepository
{
    private readonly DbContext context;
    public ProductEFCoreRepository(DbContext context)
    {
        this.context = context;
    }
    public void CreateProduct<T>(T productspu) where T:class,IAggregationRoot
    {
        var productdbcontext = this.context as ProductEFCoreContext;
        var productspunew = productspu as ProductSPU;
        try
        {
            productdbcontext.ProductSPU.Add(productspunew);
        }
        catch(Exception error)
        {
            throw error;
        }
    }
  
}
复制代码

上面的代码有几个要注意的方面:架构

a.首先会从产品的仓储接口作继承,经过EFCore的机制,实现了仓储接口的CreateProduct方法。ui

b.使用了产品上下文的EFCore数据访问上下文ProductEFCoreContext完成了Productspu的数据库预添加。this

c.上一个说法中,可能你们有两个疑惑,一是为何不使用productdbcontext标记ProductSPU为Added状态,而是使用.Add方法,二是为何只是完成了添加状态, 而再也不后续调用Commit或SaveChange方法真正持久化到数据库中?首先,由于将来持久化要将这个聚合中的ProductSPU聚合根与ProductSKU实体做为一个总体持久化到数据库中,而Added状态只能将当前聚合根做为添加状态,而不能同时将引用的ProductSKU对象做为添加状态,因此不能使用Added状态而使用.Add方法;其次仓储实现聚合提交时,只进行数据库预添,是由于协调领域逻辑与仓储的应用服务层用例可能涉及到多个聚合,因此可能要同时调用多个领域对象的业务逻辑,多个仓储,完成后,将多聚合做为一个总体事务作提交,因此真正的提交应该放到应用服务层更合适,而不是仓储层。spa

2.产品上架应用服务层实现:

应用服务层实际就是完成用例,经过应用服务层调用领域逻辑,而后经过应用服务层调用仓储,最后应用服务层作真正的提交,这样就把职责分的很是清楚,也在领域逻辑不依赖仓储的前提下,完成了整个用例和持久化。code

a.首先咱们在产品上下文的应用服务层项目中,创建须要添加的产品SPU与对应产品SKU的DTO对象cdn

public class AddProductSPUDTO
{
    public string SPUName { get; set; }
    public string SPUDesc { get; set; }
    public List<string> SKUSpecs { get; set; }
    public List<string> SKUUnits { get; set; }
    public List<decimal> SKUDealerPrices { get; set; }
    public List<byte[]> SKUImages { get; set; }
    public List<decimal> SKUPvs { get; set; }
}
复制代码

b.创建一个上架产品的用例服务,协调领域逻辑与仓储完成用例视频

public class AddProductSPUUseCase:BaseAppSrv
{
    private readonly IRepository irepositorycontext;
    private readonly IProductRepository iproductrepository;
    public AddProductSPUUseCase(IRepository irepositorycontext,IProductRepository iproductrepository)
    {
        this.irepositorycontext = irepositorycontext;
        this.iproductrepository = iproductrepository;
    }

    public ResultEntity<bool> AddProduct(AddProductSPUDTO addproductspudto)
    {
        var productspuid = Guid.NewGuid();
        var productskus = new List<ProductSKU>();
        for(int i = 0; i < addproductspudto.SKUSpecs.Count; i++)
        {
            var productsku = new ProductSKU().CreateProductSKU(addproductspudto.SPUName,
                productspuid, addproductspudto.SKUImages[i], addproductspudto.SKUDealerPrices[i],
                addproductspudto.SKUPvs[i], addproductspudto.SKUUnits[i], addproductspudto.SKUSpecs[i]);
            productskus.Add(productsku);
        }
        var productspu = new ProductSPU().CreateProductSPU(productspuid, addproductspudto.SPUName,
            addproductspudto.SPUDesc, productskus);
        try
        {
            using (irepositorycontext)
            {
                iproductrepository.CreateProduct(productspu);
                irepositorycontext.Commit();
            }
            return GetResultEntity(true);
        }
        catch(Exception error)
        {
            throw error;
        }
    }
}
复制代码

BaseAppSrv是你要定义的一个类,它的GetResultEntity方法功能是完成用例后后,返回接口层的数据格式,这个数据格式会进一步经过接口层返回给前端,返回的数据格式就是ResultEntity,这两个部分你们能够本身去实现,也能够参考个人微信公众号中的课程。

DDD实战进阶视频请关注微信公众号:MSSHCJ

相关文章
相关标签/搜索