I am having some difficulty working out the best way to handle a fairly complex scenario. I've seen quite a few similar questions, but none addressed this scenario to my satisfaction.
An Order (aggregate root) is created with multiple OrderLines (child entities). According to business rules, each OrderLine must maintain the same identity for the life of the Order. OrderLines have many (20+) properties and can be mutated fairly often before the Order is considered "locked". In addition, there are invariants that must be enforced at the root level; for example, each Order Line has a quantity and the total quantity for the Order cannot exceed X.
I'm not sure how to model this scenario when considering changes to OrderLines. I have 4 choices that I can conceive of, but none seem satisfactory:
1) When the time comes to modify an OrderLine, do it using a reference provided by the root. But I lose the ability to check invariant logic in the root.
var orderLine = order.GetOrderLine(id);
orderLine.Quantity = 6;
2) Call a method on the order. I can apply all invariant logic, but then I'm stuck with a proliferation of methods to modify the many properties of the OrderLine:
order.UpdateOrderLineQuantity(id, 6);
order.UpdateOrderLineDescription(id, description);
order.UpdateOrderLineProduct(id, product);
...
3) This might be easier if I treated the OrderLine as a Value Object, but it has to maintain the same identity per business requirements.
4) I can grab references to the OrderLines for modifications that do not affect invariants, and go through the Order for those that do. But then what if invariants are affected by most of the OrderLine properties? This objection is hypothetical, since only a few properties can affect invariants, but thhat can change as we uncover more business logic.
Any suggestions are appreciated...do not hesitate to let me know if I'm being dense.