• DDD实战进阶第一波(十四):开发一般业务的大健康行业直销系统(订单上下文应用服务用例与接口)


    上一篇文章我们主要讲了订单上下文的领域逻辑,在领域逻辑中完成了订单项的计算逻辑、订单的计算逻辑以及如何生成相应的实体code,这篇文章我们通过

    在应用服务中实现一个下单的用例,来将这些领域逻辑以及仓储整合起来,完成一个下单的用例。

    先看下单用例主体的代码:

     public class CreateOrderUseCase:BaseAppSrv
        {
            private readonly IOrderRepository iorderrepository;
            private readonly IDealerRepository idealerrepository;
            private readonly IRepository[] irepositories;
            
    
            public CreateOrderUseCase(IOrderRepository iorderrepository,IDealerRepository idealerrepository,
                params IRepository[] irepositories)
            {
                this.iorderrepository = iorderrepository;
                this.idealerrepository = idealerrepository;
                this.irepositories = irepositories;
            }
            public ResultEntity<bool> CreateOrder(OrderDTO orderdto)
            {
                var orderid = Guid.NewGuid();
                Orders order = new Orders();
                var productskus = new List<ProductSKU>();
                for(int i = 0; i < orderdto.ProductSPUNames.Count; i++)
                {
                    var productsku = new ProductSKU();
                    productsku.ProductSPUName = orderdto.ProductSPUNames[i];
                    productsku.DealerPrice = orderdto.ProductDealerPrices[i];
                    productsku.PV = orderdto.ProductPVS[i];
                    productsku.Id = orderdto.ProductSKUIds[i];
                    productsku.Spec = orderdto.ProductSepcs[i];
                    productskus.Add(productsku);
                }
                var contact = new Contact();
                contact.ContactName = orderdto.ContactName;
                contact.ContactTel = orderdto.ContactTel;
                contact.Province = orderdto.Privence;
                contact.City = orderdto.City;
                contact.Zero = orderdto.Zero;
                contact.Street = orderdto.Street;
    
                var orders = order.CreateOrders(orderid, orderdto.DealerId, productskus, orderdto.Counts,
                    contact);
    
                try
                {
                    //using (var tansaction = new TransactionScope())
                    //{
                        using (irepositories[1])
                        {
                            idealerrepository.SubParentEleMoney(orderdto.DealerId, order.OrderTotalPrice.TotalPrice);
                            idealerrepository.AddDealerPV(orderdto.DealerId, order.OrderTotalPV.TotalPV);
                            irepositories[1].Commit();
    
                        }
    
                        using (irepositories[0])
                        {
                            iorderrepository.CreateOrder(orders);
                            irepositories[0].Commit();
                        }
                    return GetResultEntity(true);
                        //tansaction.Complete();
                    //}
                }
                catch(EleMoneyNotEnoughException error)
                {
                    throw error;
                }
                catch(Exception error)
                {
                    throw error;
                }
                
            }
        }

    IOrderRepository仓储接口主要完成订单的预持久化工作,我们来看下它的实现:

    public class OrderEFCoreRepository : IOrderRepository
        {
            private readonly DbContext context;
                
            public OrderEFCoreRepository(DbContext context)
            {
                this.context = context;
            }
            public void CreateOrder<T>(T order) where T:class,IAggregationRoot
            {
                var ordercontext = this.context as OrderEFCoreContext;
                var ordernew = order as Orders;
                try
                {
                    ordercontext.Order.Add(ordernew);
                }
                catch(Exception error)
                {
                    throw error;
                }
            }
       } 

    IDealerRepository仓储接口主要用来下单完成后,扣减对应经销商的电子币与累加PV,相关方法实现代码如下:

    public void SubParentEleMoney(Guid parentdealerid, decimal subelemoney)
            {
                var dealercontext = this.context as DealerEFCoreContext;
                var parentdealer = dealercontext.Dealer.Single(p => p.Id == parentdealerid);
                parentdealer.TotalEleMoney = parentdealer.TotalEleMoney - subelemoney;
                if (parentdealer.TotalEleMoney < 0)
                {
                    throw new EleMoneyNotEnoughException("电子币不够进行此操作!");
                }
                try
                {
                    dealercontext.Entry(parentdealer).State = EntityState.Modified;
                }
                catch(Exception error)
                {
                    throw error;
                }
            }
    
            public void AddDealerPV(Guid dealerid, decimal orderpv)
            {
                var dealercontext = this.context as DealerEFCoreContext;
                var dealer = dealercontext.Dealer.Single(p => p.Id == dealerid);
                dealer.TotalPV = dealer.TotalPV +orderpv;
                try
                {
                    dealercontext.Entry(dealer).State = EntityState.Modified;
                }
                catch (Exception error)
                {
                    throw error;
                }
            }

    IRepository[]用于订单与经销商两个的数据访问仓储,完成真正的持久化,在第一部分主体代码中注释掉的using (var tansaction = new TransactionScope())与

    tansaction.Complete();是因为在.net core 2.0版本中,不支持多个数据访问上下文的事务,在.net core 2.1版本中可以使用,这样就完成了订单数据与经销商

    数据的事务一致性。

    最后我们通过webapi完成对应用服务的调用,实现代码如下。

    [HttpPost]
            [Route("CreateOrder")]
            public ResultEntity<bool> CreateOrder([FromBody] OrderDTO orderdto)
            {
                var result = new ResultEntity<bool>();
                var ordercontext = new OrderEFCoreContext();
                var dealercontext = new DealerEFCoreContext();
                var irepository = new EFCoreRepository(ordercontext);
                var irepository1 = new EFCoreRepository(dealercontext);
                var iorderrepository = new OrderEFCoreRepository(ordercontext);
                var idealerrepository = new DealerEFCoreRepository(dealercontext);
                var createorderusecase = new CreateOrderUseCase(iorderrepository, idealerrepository,
                    irepository, irepository1);
                try
                {
                    result = createorderusecase.CreateOrder(orderdto);
                    result.Count = 1;
                    result.IsSuccess = true;
                    result.Msg = "下单成功!";
                }
                catch (EleMoneyNotEnoughException error)
                {
                    result.ErrorCode = 300;
                    result.Msg = error.Message;
                }
                catch (Exception error)
                {
                    result.ErrorCode = 200;
                    result.Msg = error.Message;
                }
                return result;
            }

    因为这里只是做演示,具体接口与实现没有通过依赖注入框架注入,这部分内容可以自己去实现。

    QQ讨论群:309287205 

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

  • 相关阅读:
    Electron dialog 对话框的使用
    Electron BrowserView 的使用
    自动化测试相关
    使用chrome开发者工具中的performance面板解决性能瓶颈
    Electron window.open 函数 和 Browser-window-proxy 对象的使用
    Electron webview 标签
    Electron File对象
    Electron 进程
    JAVA日报
    JAVA日报
  • 原文地址:https://www.cnblogs.com/malaoko/p/9177194.html
Copyright © 2020-2023  润新知