您的位置:首页 > 编程语言 > ASP

Asp.net Core 系列之--3.领域、仓储、服务简单实现

2019-11-11 21:59 1436 查看

ChuanGoing 2019-11-11 

   距离上篇近两个月时间,一方面时因为其他事情耽搁,另一方面也是之前准备不足,关于领域驱动有几个地方没有想通透,也就没有继续码字。目前网络包括园子里大多领域驱动设计的文章,关于仓储者一层都没有详细的说明,只是简单的一笔带过:领域驱动不关心具体的持久化如何落地。但是,作为"猿人类"就不可避免的绕不开持久化。本篇将会简略的介绍利用Dapper这个轻量级的ORM来实现如何持久化。

本篇学习曲线:

1.领域模型

2.领域仓储

3.简单服务实现

领域模型设计

  我这里用常见的电商业务模型来介绍领域模型的设计,因篇幅有限,这里主要介绍订单与订单明细模型,基于如下业务:

1.创建订单时生成订单号、计算商品的总价同时生成订单明细。

2.根据订单号获取订单信息

  我的这个例子基本上涵盖了领域模型的主要几种业务组合:领域-实体-值对象,这几个基本概念这里不做赘述,园子里一搜一大堆。

public partial class Order : DomainEntity<Guid>
{
/// <summary>
/// 订单流水号
/// </summary>
public string Sn { get; private set; }
/// <summary>
/// 总价
/// </summary>
public decimal TotalPrice { get; private set; }
/// <summary>
/// 状态
/// </summary>
public OrderStatus Status { get; private set; }
/// <summary>
/// 支付时间
/// </summary>
public long PaymentTime { get; private set; }
/// <summary>
/// 过期时间
/// </summary>
public long ExpireTime { get; private set; }
/// <summary>
/// 备注
/// </summary>
public string Description { get; private set; }
/// <summary>
/// 用户
/// </summary>
public Guid UserId { get; private set; }

public string Adress { get; private set; }

/// <summary>
/// 订单明细
/// </summary>
[Ignore]
public List<OrderItem> OrderItems { get; private set; }
}
订单
public partial class OrderItem : Entity<Guid>
{
/// <summary>
/// 订单编号
/// </summary>
public Guid OrderId { get; private set; }
/// <summary>
/// 商品编号
/// </summary>
public Guid ProductId { get; private set; }
/// <summary>
/// 商品单价
/// </summary>
public decimal Price { get; private set; }
/// <summary>
/// 数量
/// </summary>
public int Count { get; private set; }
/// <summary>
/// 加入时间
/// </summary>
public long JoinTime { get; private set; }
}
订单详情

可以看到Order类为DomainEntity(领域实体-聚合根),OrderItem为Entity(实体),Order和OrderItem组成一个业务聚合。为什么这么划分呢?有两方面的原因:

1.本例不涉及复杂业务,没有直接针对订单明细的业务操作

2.订单明细依赖于订单,生命周期随着订单主体产生和消逝

 订单和订单明细都被设计为"partial",因为到目前为止,我们的实体类还是POCO,也就是通常所说的贫血模型。因此,为了赋予模型活力,我们需要为其添加某些行为:

public partial class Order
{
public void Add(Guid userId, Adress adress, string description, List<OrderItem> orderItems)
{
Sn = Guid.NewGuid().ToString("N");
TotalPrice = orderItems.Sum(i => i.Price * i.Count);
Status = OrderStatus.TobePaid;
ExpireTime = DateTimeOffset.Now.AddMinutes(-30).ToUnixTimeMilliseconds();
UserId = userId;
Adress = adress.ToString();
Description = description;
orderItems.ForEach(i =>
{
i.SetOrder(this);
});
SetItems(orderItems);
}

public void Pay()
{
Status = OrderStatus.Paid;
PaymentTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
}

public void SetItems(List<OrderItem> orderItems)
{
OrderItems = orderItems;
}
}
订单行为

这样,我们给领域赋予了某些行为。

领域仓储

结合我上篇Asp.net Core 系列之--2.ORM初探:Dapper实现MySql数据库各类操作介绍的仓储示例,这里为领域模型单独设计了"领域仓储层"

public class OrderRepository : DapperRepository<Order, Guid>, IOrderRepository
{
public OrderRepository(IComponentContext container, IDapperDbContext dbContext)
: base(container, dbContext)
{

}

public Order GetBySn(string sn)
{
var order = QuerySingleOrDefault<Order>("SELECT * FROM `Order` WHERE `Sn`=@Sn;", new
{
Sn = sn
});
if (order != null)
{
order.SetItems(Query<OrderItem>("SELECT * FROM `OrderItem` WHERE `OrderId`=@OrderId;", new
{
OrderId = order.Id
}).ToList());
}
return order;
}
}
领域仓储

领域仓储实现了Domain中定义的接口

public interface IOrderRepository : IRepository<Order, Guid>, IScopeInstance
{
Order GetBySn(string sn);
}
订单仓储接口定义

值得注意的时,领域仓储层这里起到了承上启下的作用,隔离了领域对于持久化层的直接依赖。

简单服务实现

    接下来,我们实现如何在业务服务层调用领域仓储实现数据的持久化。新建Application项目:

 

 定义订单接口服务

public interface IOrderService : IScopeInstance
{
void Add(OrderViewModel order);
OrderViewResult Get(string sn);
}

订单服务实现

public void Add(OrderViewModel view)
{
if (view == null) new Exception("参数无效");
var order = new Order();
Mapper.Map(view, order);

order.Add(view.UserId, view.Adress, view.Description, order.OrderItems);
_repo.Insert(order);
order.OrderItems.ForEach(i => _itemRepo.Insert(i));
}

public OrderViewResult Get(string sn)
{
var order = _repo.GetBySn(sn);

OrderViewResult result = new OrderViewResult();
return order == null ? null : Mapper.Map(order, result);
}

在Webapi项目控制器文件夹下新建OrderController

public class OrderController : Controller
{
private readonly IOrderService _service;

public OrderController(IOrderService service)
{
_service = service;
}

[HttpPost]
public void Add([FromBody]OrderViewModel order)
{
_service.Add(order);
}

[HttpGet]
public OrderViewResult Get([FromQuery]string sn)
{
return _service.Get(sn);
}
}

具体代码请看篇末源代码链接

这样,我们实现了领域模型的持久化。

回顾

  回顾一下本篇内容,分别介绍了:领域模型、领域仓储、简单服务的实现,然后利用postman模拟http请求演示了数据的创建与获取。

  本篇只是简单的介绍了领域服务及相关概念,后面有机会再做详细讨论,下篇将介绍日志模块和权限模块。

代码

  本篇涉及的源码在Github的https://github.com/ChuanGoing/Start.git  的Domain分支可以找到。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: