Решение для дерева категорий с меньшим количеством запросов? - PullRequest
0 голосов
/ 13 января 2010

В основном модель выглядит так:

----------------------------------
| CAT_ID | CAT_NAME | CAT_PARENT |
----------------------------------

которые делают это рекурсивными отношениями. Но как мы должны использовать эту модель в нашем веб-приложении MVP Asp.net с наименьшим количеством запросов. Мое временное решение - передать объект в функцию и позволить функции передавать объект вместо запроса, но это код, который я пробовал:

public string CategoryTree(this HtmlHelper html, IEnumerable<Category> categories, int? parent)
{
    parent = parent ?? 0;
    string htmlOutput = string.Empty;
    var cat = categories.Where(d => d.CAT_PARRENT == parent.Value);
    if (cat.Count() > 0)
    {
        htmlOutput += "<ul>";
        foreach (Category category in cat)
        {
            htmlOutput += "<li>";
            htmlOutput += category.CAT_NAME;
            htmlOutput += html.CategoryTree(categories, category.CAT_ID);
            htmlOutput += "</li>";
        }
        htmlOutput += "</ul>";
    }

    return htmlOutput;
}

но это генерирует как 4 запроса на 4 строки категории. Так что это не хорошее решение для этой проблемы. Я использую linq to sql.

1 Ответ

1 голос
/ 13 января 2010

Не забывайте, что .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, но это идея.

...