Sum(), ForEach() with Lambda in a hierarchical List Collection
You can create lookup for children. That will involve single enumeration over items collection instead of enumerating all items for each calculation of each item.

I.e. you currently have 2 * N * N iterations for calculating child count and child item count. With lookup you will have N + N + N iterations

var children = items.ToLookup(i =&gt; i.ParentId);

foreach(var item in items) 
{
    var subitems = children[item.Id];
    item.ChildCount = subitems.Count();
    item.ChildItemCount = subitems.Sum(i =&gt; i.DocumentCount) + item.DocumentCount;
}


Explanation: Let's look on this line

items.ForEach(z =&gt; z.ChildItemCount = 
    items.Where(x =&gt; x.ParentId == z.Id).Sum(y =&gt; y.DocumentCount) + z.DocumentCount);


Here for each item in items collection you enumerate every item in items collection to get only items which are children of current. That gives you N * N iterations totally. Count is calculated same way.

Now lets look on my code. 

var children = items.ToLookup(i =&gt; i.ParentId);


Here lookup is created. Internally it looks like enumerating over items and adding them to appropriate groupings of lookup. You can think of lookup as a Dictionary&lt;TKey, List&lt;TValue&gt;&gt;. 

Next we do enumerating of all items (that's another N). In body of this loop we get children of item (getting appropriate group by key is pretty fast O(1) operation, comparing to enumerating all items and filtering them). Good news here is behavior of lookup when key not found - it simply returns EmptyEnumerable (i.e. empty array of TValue), so we don't need to check anything - further calculations will work without problems:

foreach(var item in items)
{
    var subitems = children[item.Id];
    // ...
}


Next we do two operations. First is getting count of items in group. Grouping implements ICollection with Count property, and it simply returns count of items in group, without enumerating them:

item.ChildCount = subitems.Count();


Second operation is calculating sum of documents in group. Thus total number of items in all groups will be N then enumerating all groups will take N iterations:

item.ChildItemCount = subitems.Sum(i =&gt; i.DocumentCount) + item.DocumentCount;


UPDATE: Thus you want ChildItemCount to contain sum