I'm trying to flatten a List using SelectMany() method, the problem is the child/nested list's can have data or sometimes it can be empty. I want the my lambda query should at least return the data of parent list i.e. InventoryCode & InventoryDescription, because the parent collection can never be empty. I tried below query , but result count is 0 when any of the child/nested list's are empty.
public class Share
{
public string shareCode {get;set;}
public int shareNumber {get;set;}
}
public class ProductModel
{
public string productCode {get;set;}
public string productName{get;set;}
public List<Share> share{get;set;}
}
public class InventoryModel
{
public string inventoryCode {get;set;}
public string inventoryDescription {get;set;}
public List<Product> products {get;set;}
}
Note-InventoryModel is also used as list in some other model
The below code which I have written work's well when child list's are not empty, but it fails to return any data when any of the child list's is empty
var invenFlatList = lstInventory.SelectMany(x => x.products.SelectMany(y => y.shares.Select(z => new NewModel
{
inventoryCode = x.inventoryCode ,
inventoryDescription = x.inventoryDescription ,
productCode = y.productCode ,
productName= y.productName,
shareCode = z.shareCode ,
shareNumber = z.shareNumber
}))).ToList();
CodePudding user response:
Use DefaultIfEmpty()
to perform left outer join in linq. So, add this where you want to return the parent regardless of the child is available or not.
Please add null checks
in the subsequent projections to avoid null reference.
CodePudding user response:
You can use following approach using DefaultIfEmpty
with a fallback item:
List<NewModel> resultList = lstInventory
.SelectMany(inv => inv.products
.SelectMany(prod => prod.shares
.Select(share => new NewModel
{
inventoryCode = inv.inventoryCode,
inventoryDescription = inv.inventoryDescription,
productCode = prod.productCode,
productName = prod.productName,
shareCode = share.shareCode,
shareNumber = share.shareNumber
})
.DefaultIfEmpty(new NewModel
{
inventoryCode = inv.inventoryCode,
inventoryDescription = inv.inventoryDescription,
productCode = prod.productCode,
productName = prod.productName,
shareCode = null,
shareNumber = 0
})))
.ToList();