Не забывайте, что .Count () также может генерировать запрос; вы можете использовать Where (). ToList (), а затем его .Count, так как вы все равно собираетесь использовать полную коллекцию.
Альтернативным подходом было бы сначала собрать CAT_ID, получить всех связанных детей для всех из них, а затем передать дочерние элементы в качестве подсказки для сбора в ваш метод. Что-то вроде
public string CategoryTree(this HtmlHelper html, IEnumerable<Category> categories, IList<Category> cats)
{
var query = categories.Where(x => false);
// a query to select ALL new children
foreach (var parent in cat.Select(x => x.CAT_ID))
query = query.Union(categories.Where(x => x.CAT_PARENT = parent));
var newchildren = query.ToList(); // execute query for all children at once - only once
foreach (Category category in cats)
{
htmlOutput += "<li>";
htmlOutput += category.CAT_NAME;
// here we select only this category children - from already executed query results
htmlOutput += html.CategoryTree(categories, newchildren.Where(x => x.CAT_PARENT = category.CAT_ID).ToList());
htmlOutput += "</li>";
}
}
Конечно, это не окончательный код, и вам лучше использовать IN [parentid, parentid, parentid] вместо UNION, но это идея.