Reputation: 3115
I have a system where people can sent me a List<ProductCategory>
.
I need to do some mapping to my system and then save these to the database.
The incoming data is in this format:
public string ExternalCategoryID { get; set; }
public string ExternalCategoryName { get; set; }
public string ExternalCategoryParentID { get; set; }
The incoming list is in no particular order. If ExternalCategoryParentID
is null then this is a top level category. The parent child relationship can be any depth - i.e. Technology > TVs > Samsung > 3D > 40" > etc > etc
When I'm saving I need to ensure I've already saved the parent - I can't save TVs until I have saved Technology. The ExternalCategoryID
is likely to be an int but this has no relevance on the parent child relationship (a parent can have a higher or lower id than a child).
How can I order this list so I can loop through it and be certain that for any child, I have already processed it's parent.
The only way I can think of is to get all where ExternalCategoryParentID == null
then get all where the ExternalCategoryParentID
is in this "Top Level" list, then get the next set of children... etc. but this can't be the best solution. I'd prefer to sort first, then have a single loop to process. I have found this post, but it relies on createdDate
which isn't relevant to me.
Upvotes: 0
Views: 1535
Reputation: 3115
Turns out it wasn't so difficult after all. I wrote this function to do it - you pass in the original list and it will return a sorted list.
It works by looping through the list checking if there are any items in the list that have id == current items parentid
. If there is one, we ignore that item and continue. if there aren't any, we add the current item to the sortedList
and remove it from the original list and continue. This ensures that items are inserted in the sorted list after their parent.
private List<HeisenbergProdMarketplaceCategory> SortByParentChildRelationship(List<HeisenbergProdMarketplaceCategory> heisenbergMarketplaceCategories)
{
List<HeisenbergProdMarketplaceCategory> sortedList = new List<HeisenbergProdMarketplaceCategory>();
//we can check that a category doesn't have a parent in the same list - if it does, leave it and continue
//eventually the list will be empty
while(heisenbergMarketplaceCategories.Count > 0)
{
for (int i = heisenbergMarketplaceCategories.Count-1; i >= 0; i--)
{
if (heisenbergMarketplaceCategories.SingleOrDefault(p => p.ExternalCategoryID == heisenbergMarketplaceCategories[i].ExternalCategoryParentID) == null)
{
sortedList.Add(heisenbergMarketplaceCategories[i]);
heisenbergMarketplaceCategories.RemoveAt(i);
}
}
}
return sortedList;
}
Upvotes: 1
Reputation: 464
We can check the field value to be null and then set int.max to it and then order by desc to get it at the top.
We can check the ExternalCategoryID = field.Value ?? int.max
and then Order by descending
.
Sample :
var query = context.Categories.Select(o => new { Obj = o, OrderID = o.OrderID ?? int.MaxValue }).OrderByDescending(o => o.OrderID).Select(o => o.Obj);
Upvotes: 0