上一篇文章我们主要讲了订单上下文的领域逻辑,在领域逻辑中完成了订单项的计算逻辑、订单的计算逻辑以及如何生成相应的实体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. 从零开始学java (五)接口与内部类

    接口,是描述类具有什么样的功能,而不是给出每个功能的实现.一个类可以implements多个接口...接口中可以含有 变量和方法.但是要注意, 接口中的变量会被隐式地指定为public static ...

  2. python3.0 第三天 文件操作

    文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下 Somehow, it seems the love I knew was alway ...

  3. Windows 自动化补丁管理

    Windows 自动化补丁管理 Desktop Central,这一倍受欢迎的补丁管理软件旨在修补可能导致安全薄弱.破坏关键系统数据或导致系统不可用的漏洞.管理此类软件漏洞对网络管理员来说简直是噩梦. ...

  4. 你了解栈溢出StackOverFloweExeption的原理吗?

    StackOverflowException的常见几种引起的方式 1.类的相互引用 2.方法的循环调用 3.属性Set方法的死循环调用 class Program : IProgram { IPers ...

  5. java操作docker示例(docker-java)

    1.首先要修改docker服务器的 /usr/lib/systemd/system/docker.service,加入紫色框的配置 2.下载docker-java 的github源码 git clon ...

  6. CentOS7 安装配置rsync

    centos7自带rsync,今天简单记录下. rsync安装配置步骤 服务器端: 1.修改默认配置文件/etc/rsyncd.conf,该成如下: # /etc/rsyncd: configurat ...

  7. 微信小程序------加导航

    效果图如下 这个其实很简单 在app.json上面加点代码 "window":{ "backgroundTextStyle":"light" ...

  8. 简析 __init__、__new__、__call__ 方法

    简析 __init__.__new__.__call__ 方法 任何事物都有一个从创建,被使用,再到消亡的过程,在程序语言面向对象编程模型中,对象也有相似的命运:创建.初始化.使 用.垃圾回收,不同的 ...

  9. ServiceStack.Redis记录

    一.事务 (一)AcquireLock方法 1.说明:申请对一个Key加锁(期间其他对象不能访问). 2.带using的使用,或带过期时间参数,否则锁不会自动释放. using (RedisCache ...

  10. FPGA跨时钟域握手信号的结构

    FPGA跨时钟数据传输,是我们经常遇到的问题的,下面给出一种跨时钟握手操作的电路结构.先上图 先对与其他人的结构,这个结构最大的特点是使用 req 从低到高或者高到低的变化 来表示DIN数据有效并开始 ...