Increase Perfomance of Nested Object Instantiation C#
Option 1) You can create a DataRelations between the two Data Tables and change the loop to fill in both classes at the same time.  This would require you do change the code that converts the results set into C# classes.  Microsoft has an example of GetChildRows and navigation here 

Option 2) Otherwise you could also create a DataView and set the Sort property on the child Data Table and use FindRows method. Again will require you to change how you convert from datatable to C# classes.  I'd lean toward the first option instead of creating another set of data objects just for sorting.

Option 3) I'm guessing it will not be much better performance but you can try is using the Linq GroupJoin 

foreach (var data in items.GroupJoin(usageItems,
    x =&gt; new {x.ItemCode, x.WarehouseCode},
    x =&gt; new {x.ItemCode, x.WarehouseCode},
    (itm, usg) =&gt; new
    {
        item = itm,
        usage = usg.ToList()
    }))
{
    data.item.Usage = data.usage;
} 


Update #1 - Couple more options. 

Option 4) Parallel the finding of data. Take Option 3 and add the AsParallel()

foreach (var data in items.AsParallel().GroupJoin(usageItems.AsParallel(),
    x =&gt; new {x.ItemCode, x.WarehouseCode},
    x =&gt; new {x.ItemCode, x.WarehouseCode},
    (itm, usg) =&gt; new
    {
        item = itm,
        usage = usg.ToList()
    }))
{
    data.item.Usage = data.usage;
} 


I still think option 1 would be the best option as it will create a binary search tree for the relationship and give best performance. 

Option 5) if you know the usageItems are sorted by the ItemCode and WarehouseCode you could just iterate over the list once and fill in the Item as it scans over the list.  This would be the most efficient but would require more complex code and also required that sort order is always correct.  While having this sort order would help Option 1 it wouldn't be required.