如何更新DDD中的聚合子级?

时间:2019-01-25 17:25:11

标签: c# asp.net-core domain-driven-design

我正在尝试使用asp.net核心的DDD风格的体系结构,但是在理解如何创建聚合根子实体后遇到困难。

我有一个订单类,其中包含OrderLines的只读列表。这些订单行可以更新或从订单中删除。订单将始终在单个交易中在前端进行编辑(发布到API)。

我已经在订单汇总中为此创建了方法,但是感觉逻辑错了。这是更新/删除DDD中子实体的正确方法吗?

由于订单将以PUT方式进入API,因此我检查数据库中实体上是否有任何项目不在传入数据中。如果没有,我将其删除。如果是这样,我会对其进行更新。

这是否属于服务类? DDD的最佳做法是什么?

public class Order : BaseEntity, IAggregateRoot
    {
        public Order(List<OrderItem> items, Address shippingAddress, int customerId)
        {
            ShipToAddress = shippingAddress ?? throw new Exception("Can not be null");
            _orderItems = items ?? throw new Exception("Can not be null");
            CustomerId = customerId;
            Status = OrderStatus.Processing;
        }

        private readonly List<OrderItem> _orderItems = new List<OrderItem>();

        public IReadOnlyCollection<OrderItem> OrderItems => _orderItems.AsReadOnly();

        public void AddOrUpdateOrderItem(ProductOrdered itemOrdered, decimal unitPrice, int units, DateTime deliverDate, int orderItemId)
        {
            var existingOrderLine = _orderItems.Where(o => o.Id == orderItemId)
                .SingleOrDefault();

            if (existingOrderLine != null)
            {
                existingOrderLine.Update(itemOrdered, unitPrice, units, deliverDate);
            }
            else
            {
                //add validated new order item
                var orderItem = new OrderItem(itemOrdered, unitPrice, units, deliverDate);
                _orderItems.Add(orderItem);
            }
        }
        public void RemoveOrderLines(List<int> orderItemIds)
        {   
            foreach (var item in _orderItems.ToList())
            {
                var containsItem = orderItemIds.Any(newOrderLine => newOrderLine == item.Id);
                if (!containsItem)
                {
                    _orderItems.Remove(item);
                }
            }
        }
    }

OrderLine:

public class OrderItem : BaseEntity
    {
        public ProductOrdered ItemOrdered { get; private set; }
        public decimal UnitPrice { get; private set; }
        public int Units { get; private set; }
        public DateTime DeliveryDate { get; set; }
        public OrderLineStatus OrderLineStatus { get; set; }

        private OrderItem()
        {
            // required by EF
        }

        public OrderItem(ProductOrdered itemOrdered, decimal unitPrice, int units, DateTime deliverDate)
        {
            ItemOrdered = itemOrdered;
            UnitPrice = unitPrice;
            Units = units;
            DeliveryDate = deliverDate;
            OrderLineStatus = OrderLineStatus.Waiting;
        }

        public void Update(ProductOrdered itemOrdered, decimal unitPrice, int units, DateTime deliverDate)
        {
            ItemOrdered = itemOrdered;
            UnitPrice = unitPrice;
            Units = units;
            DeliveryDate = deliverDate;
        }
    }

1 个答案:

答案 0 :(得分:0)

  

我已经在订单汇总中为此创建了方法,但是感觉逻辑错了。这是更新/删除DDD中的子实体的正确方法吗?   是。我只是不喜欢在一个中定义2个单独的用例。我会在seaparate方法中添加,而在另一个中进行Update。关于放置端点。考虑使用基于任务的UI。它比CrudBased put操作更适合DDD。因此,请定义命令-AddLineItemCommand,UpdateLineItemCommand,RemoveLineItemCommand以及它们的不同POST操作。分别对待每个用例。