上一篇文章我们主要讲了订单上下文的领域逻辑,在领域逻辑中完成了订单项的计算逻辑、订单的计算逻辑以及如何生成相应的实体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实战进阶视频请关注微信公众号:

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

  1. DDD实战进阶第一波(十):开发一般业务的大健康行业直销系统(实现经销商登录仓储与逻辑)

    上一篇文章主要讲了经销商注册的仓储和领域逻辑的实现,我们先把应用服务协调完成经销商注册这部分暂停一下,后面文章统一讲. 这篇文章主要讲讲经销商登录的仓储和相关逻辑的实现. 在现代应用程序前后端分离的实 ...

  2. DDD实战进阶第一波(一):开发一般业务的大健康行业直销系统(概述)

    本系列文章 DDD实战进阶第一波(一):开发一般业务的大健康行业直销系统(概述) DDD实战进阶第一波(二):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架一) 近年来,关于如何开发基于 ...

  3. DDD实战进阶第一波(二):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架一)

    要实现软件设计.软件开发在一个统一的思想.统一的节奏下进行,就应该有一个轻量级的框架对开发过程与代码编写做一定的约束. 虽然DDD是一个软件开发的方法,而不是具体的技术或框架,但拥有一个轻量级的框架仍 ...

  4. DDD实战进阶第一波(八):开发一般业务的大健康行业直销系统(业务逻辑条件判断最佳实践)

    这篇文章其实是大健康行业直销系统的番外篇,主要给大家讲讲如何在领域逻辑中,有效的处理业务逻辑条件判断的最佳实践问题. 大家都知道,聚合根.实体和值对象这些领域对象都自身处理自己的业务逻辑.在业务处理过 ...

  5. DDD实战进阶第一波(三):开发一般业务的大健康行业直销系统(搭建支持DDD的轻量级框架二)

    了解了DDD的好处与基本的核心组件后,我们先不急着进入支持DDD思想的轻量级框架开发,也不急于直销系统需求分析和具体代码实现,我们还少一块, 那就是经典DDD的架构,只有了解了经典DDD的架构,你才能 ...

  6. DDD实战进阶第一波(五):开发一般业务的大健康行业直销系统(实现产品上下文领域层)

    从这篇文章开始,我们根据前面的DDD理论与DDD框架的约束,正式进入直销系统案例的开发. 本篇文章主要讲产品上下文中的领域层的主要实现,先简单讲下业务方面的需求:产品SPU与产品SKU,产品SPU主要 ...

  7. DDD实战进阶第一波(六):开发一般业务的大健康行业直销系统(实现产品上下文仓储与应用服务层)

    前一篇文章我们完成了产品上下文的领域层,我们已经有了关于产品方面的简单领域逻辑,我们接着来实现产品上下文关于仓储持久化与应用层的用例如何来协调 领域逻辑与仓储持久化. 首先大家需要明确的是,产品上下文 ...

  8. DDD实战进阶第一波(九):开发一般业务的大健康行业直销系统(实现经销商上下文仓储与领域逻辑)

    上篇文章主要讲述了经销商上下文的需求与POCO对象,这篇文章主要讲述该界限上下文的仓储与领域逻辑的实现. 关于界限上下文与EF Core数据访问上下文参考产品上下文相应的实现,这里不再累述. 因为在经 ...

  9. DDD实战进阶第一波(十一):开发一般业务的大健康行业直销系统(实现经销商代注册用例与登录令牌分发)

    前两篇文章主要实现了经销商代注册的仓储与领域逻辑.经销商登录的仓储与相关逻辑,这篇文章主要讲述经销商代注册的用例与经销商登录的查询功能. 一.经销商代注册用例 在经销商代注册用例中,我们需要传递经销商 ...

  10. DDD实战进阶第一波(十三):开发一般业务的大健康行业直销系统(订单上下文领域逻辑)

    前一篇文章主要讲了订单上下文的POCO模型,其中订单与订单项中有大量的值对象.这篇文章主要讲讲这些值对象以及订单项.订单相关的领域逻辑. 1.ProductSKUs值对象领域逻辑:ProductSKU ...

随机推荐

  1. 【信号与线性系统】为什么求解零输入响应时转移算子H(p)不能约分,但计算单位冲激响应时却可以约分?

    为什么求零输入响应rZI时转移算子H(p)不能约分? . . . 我们知道,求零输入响应rZI的实质其实是求解微分方程 D(p)r(t) = N(p)e(t) 的解.由于这里 e(t)=0 ,所以这是 ...

  2. kettle连接oracle报错oracle.i18n.text.converter.CharacterConverter.OGS.getInstance(I)Loracle/i18n/text/converter/CharacterConverter

    问题背景1:需要将一张excel中的数据导入到数据库中,并且还有关联转换和去重的处理问题,且此excel表不是固定的,需要写一个脚本 当新的excel拿来的时候,可以直接导入即可.所以我想用kettl ...

  3. (PMP)解题技巧和典型题目分析(0903-2班)

    1.计算题 ,5 2.概念题,少 3.情景题,很多 C B C D ------------------------------------------------------------------ ...

  4. boost--文件、目录操作

    filesystem库是文件系统操作库,可以使用其中的basic_path类用来操作目录.文件,使用需要包含编译好的system库和filesystem库,我们一般不直接使用basic_path,而是 ...

  5. bootstrap-datepicker简单使用

    粗略整理,可能存在其他的方式请大家多多指教 选择年份 html <div class="dropdown"> <label class="search- ...

  6. 20155205 郝博雅 Exp4 恶意代码分析

    20155205 郝博雅 Exp4 恶意代码分析 一.实验目标 1.监控你自己系统的运行状态,看有没有可疑的程序在运行. 2.分析一个恶意软件,就分析Exp2或Exp3中生成后门软件:分析工具尽量使用 ...

  7. ModelAndView返回json对象的方法

    这是在spring4之后. @RequestMapping(value = "/returnjson") public ModelAndView getfsd(){ ModelAn ...

  8. Nginx 教程(2):性能

    tcp_nodelay, tcp_nopush 和 sendfile tcp_nodelay 在 TCP 发展早期,工程师需要面对流量冲突和堵塞的问题,其中涌现了大批的解决方案,其中之一是由 John ...

  9. 28.TreeSet

    与HashSet是基于HashMap实现一样,TreeSet同样是基于TreeMap实现的.在前一篇中详细讲解了TreeMap实现机制,如果客官详细看了这篇博文或者对TreeMap有比较详细的了解,那 ...

  10. Windows 10 IoT Core 17127 for Insider 版本更新

    昨天,微软发布了Windows 10 IoT Core 17127 for Insider 版本更新,本次更新只修正了一些Bug,没有发布新的特性.相比于17120,修复了一个已知的问题. 一些已知的 ...