One of the biggest issues here is that there is a careful balance to strike between theoretical elegance and practical performance considerations.
From a logic perspective, it's much simpler to blindly rely on the notion that all data is available, so that you don't have to write logic to account for additional fetching or second-guessing of the possibly incomplete data set you're dealing with.
From a data perspective, you want to cut down any unnecessary data fetching as much as possible, and would prefer if the logic simply worked with an incomplete (but functionally viable) data set.
But in practice, machines have limited performance and both business priorities and workloads can lead to such a blanket "load all" behavior being cost-ineffective in terms of the required hardware.
A book on the theory of DDD and aggregate roots tends to stick to its theory rather than discussing myriad possible compromises for the sake of performance.
There is also the consideration of how you define your aggregates. Purists will argue that you only label something as an aggregate specifically when you do not object to the entire aggregate being loaded in, as the aggregate represents the indivisible "data unit".
However, there may be contextual considerations here, where your aggregate is generally loaded in its entirety, but for one particular use case (e.g. a sizeable bulk import) creates more performance issues than you can manage. It would be an overcorrection to throw out the entire aggregate concept across the board because of one solitary use case (in a sea of use cases) that doesn't quite fit the pattern.
Long story short, pattern are there to help. And when they don't help, consider not using them. But then you do lose the pattern's benefit.
My question is: to edit a specific OrderItem should I load all OrderItems and build the complete Aggregate or can I retrieve from repository just the Order data and the specific OrderItem data and follow the update ?
From a "get the job done" perspective, both options are perfectly workable implementations.
The first option retains adherence to aggregate root principles, but suffers from performance issues. The second option (temporarily) dismisses the aggregate root principle in favor of performance gains.
Pick which is most important to you: design purity or performance.
Order
instance (which will obviously be instantiated and used as root ).