[.NET领域驱动设计实战系列]专题六:DDD实践案例:网上书店订单功能的实现

简介: 原文:[.NET领域驱动设计实战系列]专题六:DDD实践案例:网上书店订单功能的实现一、引言    上一专题已经为网上书店实现了购物车的功能了,在这一专题中,将继续对网上书店案例进行完善,本专题将对网上书店订单功能的实现进行介绍,现在废话不多说了,让我们来一起看看订单功能是如何实现的吧。
原文: [.NET领域驱动设计实战系列]专题六:DDD实践案例:网上书店订单功能的实现

一、引言

   上一专题已经为网上书店实现了购物车的功能了,在这一专题中,将继续对网上书店案例进行完善,本专题将对网上书店订单功能的实现进行介绍,现在废话不多说了,让我们来一起看看订单功能是如何实现的吧。

二、订单功能的实现思路

   在网上购过物的朋友,对于订单功能的流程自然不陌生,这里我还是先来梳理下下订单的一个流程:

  • 用户点击我的购物车,可以勾选对应的商品进行结算
  • 在结算页面可以提交订单来创建一个订单
  • 创建订单成功之后就是进行付款了。

  一般购物网站下订单的流程分上面3步,由于在本案例中并没有对接第三方的支付平台,所以这里就没有上面第三步的过程了。即在网上书店案例中订单提交成功之后就是已付款状态。

  从上面下订单流程我们就可以知道订单功能的实现思路:

  • 用户点击购物车中购买商品按钮来进行下订单,此时触发控制器中的结算方法进行调用
  • 结算方法通过调用OrderService服务中的结算方法
  • 由于订单的创建涉及了3个实体操作,包括购物车实体,购物车项实体和订单实体。所以这里需要引入领域服务。因为创建订单这个操作涉及了多个实体,则这个业务逻辑放在每个实体中都不合适,因为并属于单独一个实体的逻辑。所以这里引入领域服务来实现这种涉及多个实体的操作。
  • 则OrderService服务中的结算方法通过调用领域服务中的CreateOrder方法来完成订单创建的功能。
  • 领域服务中可以调用对应的实体仓储来完成实体的持久化。这里需要注意的一点:因为领域服务涉及多个实体的持久化,则需要引入工作单元模式将这些实体的操作进行统一提交,要不都成功,要不都不成功。这也就是引入工作单元初衷。

  上面的思路就是订单功能的实现思路。有了上面的思路之后,实现订单功能也一目了然了。下面让我们一起在网上书店案例中实现下看看。

三、网上书店订单功能的实现

   这里我们按照上面的实现思路由下至上地去实现订单功能。

  1. 首先我们需要订单仓储来完成订单实体的持久化。具体订单仓储接口和实现如下代码所示:
// 订单仓储接口
    public interface IOrderRepository : IRepository<Order>
    {
    }

 // 订单仓储的实现类
    public class OrderRepository : EntityFrameworkRepository<Order>, IOrderRepository
    {
        public OrderRepository(IRepositoryContext context) : base(context)
        {
        }
    }

  2. 领域服务的实现。具体的领域服务接口和实现代码如下所示:

// 领域服务接口
    public interface IDomainService
    {
        Order CreateOrder(User user, ShoppingCart shoppingCart);
    }
    
    // 领域服务类型
    // 牵涉到多个实体的操作可以把这些操作封装到领域服务里
    public class DomainService : IDomainService
    {
         private readonly IRepositoryContext _repositoryContext;
        private readonly IShoppingCartItemRepository _shoppingCartItemRepository;
        private readonly IOrderRepository _orderRepository;
            
         /// <summary>
        /// 创建订单,涉及到的操作有2个:1. 把购物车中的项中购物车移除; 2.创建一个订单。
        /// 这两个操作必须同时完成或失败。
        /// </summary>
        /// <param name="user"></param>
        /// <param name="shoppingCart"></param>
        /// <returns></returns>
        public Order CreateOrder(User user, ShoppingCart shoppingCart)
        {
            var order = new Order();
            var shoppingCartItems =
                _shoppingCartItemRepository.GetAll(
                    new ExpressionSpecification<ShoppingCartItem>(s => s.ShoopingCart.Id == shoppingCart.Id));
            if (shoppingCartItems == null || !shoppingCartItems.Any())
                throw new InvalidOperationException("购物篮中没有任何物品");

            order.OrderItems = new List<OrderItem>();
            foreach (var shoppingCartItem in shoppingCartItems)
            {
                var orderItem = shoppingCartItem.ConvertToOrderItem();
                orderItem.Order = order;
                order.OrderItems.Add(orderItem);
                _shoppingCartItemRepository.Remove(shoppingCartItem);
            }
            order.User = user;
            order.Status = OrderStatus.Paid;
            _orderRepository.Add(order);
            _repositoryContext.Commit();
            return order;
        }
    }

  3. 订单服务的实现。具体订单服务实现代码如下所示:

public class OrderServiceImp : ApplicationService, IOrderService
    {
        #region Private Fileds
        private readonly IShoppingCartRepository _shoppingCartRepository;
        private readonly IShoppingCartItemRepository _shoppingCartItemRepository;
        private readonly IUserRepository _userRepository;
        private readonly IOrderRepository _orderRepository;
        private readonly IProductRepository _productRepository;
        private readonly IDomainService _domainService;
        private readonly IEventBus _eventBus;
        #endregion 

        #region Ctor
        public OrderServiceImp(IRepositoryContext context, 
            IUserRepository userRepository, 
            IShoppingCartRepository shoppingCartRepository, 
            IProductRepository productRepository, 
            IShoppingCartItemRepository shoppingCartItemRepository, 
            IDomainService domainService, 
            IOrderRepository orderRepository, 
            IEventBus eventBus) : base(context)
        {
            _userRepository = userRepository;
            _shoppingCartRepository = shoppingCartRepository;
            _productRepository = productRepository;
            _shoppingCartItemRepository = shoppingCartItemRepository;
            _domainService = domainService;
            _orderRepository = orderRepository;
            _eventBus = eventBus;
        }

        #endregion 
        
         public OrderDto Checkout(Guid customerId)
        {
            var user = _userRepository.GetByKey(customerId);
            var shoppingCart = _shoppingCartRepository.GetByExpression(s => s.User.Id == user.Id);
            var order = _domainService.CreateOrder(user, shoppingCart);

            return Mapper.Map<Order, OrderDto>(order);
        }
     
        public OrderDto GetOrder(Guid orderId)
        {
            var order = _orderRepository.GetBySpecification(new ExpressionSpecification<Order>(o=>o.Id.Equals(orderId)), elp=>elp.OrderItems);
            return Mapper.Map<Order, OrderDto>(order);
        }

        // 获得指定用户的所有订单
        public IList<OrderDto> GetOrdersForUser(Guid userId)
        {
            var user = _userRepository.GetByKey(userId);
            var orders = _orderRepository.GetAll(new ExpressionSpecification<Order>(o => o.User.Id == userId), sp => sp.CreatedDate, SortOrder.Descending, elp=>elp.OrderItems);
            var orderDtos = new List<OrderDto>();
            orders
                .ToList()
                .ForEach(o=>orderDtos.Add(Mapper.Map<Order, OrderDto>(o)));
            return orderDtos;
        }

  4. HomeController控制器中Checkout操作的实现。具体实现代码如下所示:

public class HomeController : ControllerBase
{
        /// <summary>
        /// 结算操作
        /// </summary>
        /// <returns></returns>
        [Authorize]
        public ActionResult Checkout()
        {
            using (var proxy = new OrderServiceClient())
            {
                var model = proxy.Checkout(this.UserId);
                return View(model);
            }
        }

        [Authorize]
        public ActionResult Orders()
        {
            using (var proxy = new OrderServiceClient())
            {
                var model = proxy.GetOrdersForUser(this.UserId);
                return View(model);
            }
        }

        [Authorize]
        public ActionResult Order(string id)
        {
            using (var proxy = new OrderServiceClient())
            {
                var model = proxy.GetOrder(new Guid(id));
                return View(model);
            }
        }
}

  这样我们就在网上书店中实现了订单功能了。具体的视图界面也就是上一专题中实现的购物车页面。下面具体看看订单的具体实现效果:

  结算页面:

  点击确认购买按钮,在弹出框中点击确认来完成订单的创建:

  通过我的订单来查看所有订单页面:

四、总结

  到此,网上书店案例的订单功能的实现就完成了,在接下来的专题将继续对该案例进行完善,在下一专题中将为该案例引入后台管理操作。商家或管理员可以进入后台管理来对用户订单进行确认发货,以及添加商品,分类等操作。具体实现请见下一专题。

  本专题中所有实现源码下载:https://github.com/lizhi5753186/OnlineStore_Second/

 

目录
相关文章
|
17天前
|
开发框架 .NET 中间件
.net8 使用 license 证书授权案例解析
本文介绍了如何使用 `.NET CLI` 创建并改造一个 `ASP.NET Core Web API` 项目,以实现基于许可证的授权机制。具体步骤包括创建项目、添加必要的 NuGet 包(如 `Standard.Licensing` 和 `Swashbuckle.AspNetCore`),以及修改 `Program.cs` 文件以集成自定义的许可证验证中间件。项目结构中新增了 `LicenseController` 接口用于处理授权相关操作,并通过测试流程验证了默认天气接口在未授权和授权状态下的响应情况。整个过程确保了应用程序能够在启动时正确验证许可证,保障系统的安全性与可控性。
51 8
.net8 使用 license 证书授权案例解析
|
3月前
|
开发框架 搜索推荐 算法
一个包含了 50+ C#/.NET编程技巧实战练习教程
一个包含了 50+ C#/.NET编程技巧实战练习教程
158 18
|
3月前
|
Linux API C#
基于 .NET 开发的多功能流媒体管理控制平台
基于 .NET 开发的多功能流媒体管理控制平台
69 9
|
3月前
|
XML C# 数据格式
一个.NET开源、免费、功能强大的 PDF 处理工具
一个.NET开源、免费、功能强大的 PDF 处理工具
|
3月前
|
网络协议 C#
3款.NET开源、功能强大的通讯调试工具,效率提升利器!
3款.NET开源、功能强大的通讯调试工具,效率提升利器!
72 10
|
3月前
|
监控 前端开发 API
一款基于 .NET MVC 框架开发、功能全面的MES系统
一款基于 .NET MVC 框架开发、功能全面的MES系统
|
4月前
|
消息中间件 监控 数据可视化
基于.NET开源、功能强大且灵活的工作流引擎框架
基于.NET开源、功能强大且灵活的工作流引擎框架
108 3
|
4月前
|
XML 开发框架 .NET
.NET 9 中 LINQ 新增功能实操
.NET 9 中 LINQ 新增功能实操
|
4月前
|
网络协议 Unix Linux
精选2款C#/.NET开源且功能强大的网络通信框架
精选2款C#/.NET开源且功能强大的网络通信框架
141 0
|
4月前
|
开发框架 JavaScript 前端开发
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
2024年全面且功能强大的.NET快速开发框架推荐,效率提升利器!
120 0

热门文章

最新文章