Problem:
When importing products from XLSX, the ImportManger class (ImportProductsFromXlsx function) uses the following code to get all categories and build the formatted category dictionary (line 762):
var allCategories = _categoryService.GetAllCategories(showHidden: true).ToDictionary(c => c.GetFormattedBreadCrumb(_categoryService), c => c);
This code is HORRIBLY slow because of this call:
c.GetFormattedBreadCrumb(_categoryService)
This is especially bad if you have many categories, or a larger product list.
Solution:
The good news is that there are actually 2 overloaded GetFormattedBreadCrumb functions, one takes a category service, the other takes a list of "allCategories". There is no reason to pass the category service and go through EF when we just loaded all categories in the preceding step in the code.
The fix becomes extremely simple, just switching to the other overloaded function for GetFormattedBreadCrumb.
Below is a change I put in:
var allCategoryList = _categoryService.GetAllCategories(showHidden: true);
var allCategories = allCategoryList.ToDictionary(c => c.GetFormattedBreadCrumb(allCategoryList), c => c);
As you can see, we are already getting a list of allCategories, so it's just a matter of using the data we already have, and passing it to a function that already exists to use that data. It's as simple as that.
Performance Tests:
We have 845 categories in our store. Loading a file with 10,000 products.
Before fix: After hitting the "allCategories" line, the original code ran for another 25 minutes to step to the next line.
After the fix: The same line of code completed in under 1 second. The performance became so immensely better that we can't even make a comparison, from 25+ minutes, to under 1 second, with this simple 1 line code change.