Проблема NHibernate N + 1 при создании меню в Spark View Engine ASP.NET MVC - PullRequest
1 голос
/ 11 марта 2011

У меня есть сайт с тысячами категорий.Я создаю меню, в котором перечислены корневые категории и при наведении указывается дочерние категории (и, возможно, еще один уровень).

В моем представлении с искрой у меня есть это:

<ul class="menu">
        <li each="var category in categories">
            ${Html.ActionLink(category.Name, "Index", "Category", new {id=category.Id}, new {@class="drop"})}
            <div class="dropdown_1column">
                <div class="col_1 firstcolumn">
                    <ul class="levels">
                        <li each="var subcategory1 in category.ChildCategories">
                            ${Html.ActionLink(subcategory1.Name, "Index", "Category", new {id=subcategory1.Id}, new {@class="drop"})}                            
                        </li>
                    </ul>
                </div>
            </div>
        </li>
    </ul>

Вмой репозиторий категорий У меня есть это:

var categories = session.CreateCriteria(typeof(Category))
                .Add(Restrictions.IsEmpty("ParentCategories")).Add(!Restrictions.Eq("Name", "Hide"))
                .AddOrder(Order.Asc(sortBy))
                .SetFetchMode("ParentCategories", FetchMode.Eager)
                .List<Category>();

Я получаю предупреждение N + 1 в NHProfiler, когда механизм представления искры циклически перебирает дочерние категории.Поскольку дочерние категории являются отложенными, NHibernate запускает выбор для каждой дочерней категории каждой корневой категории.Если я установлю для ChildCategories FetchMode значение Eager, то NH пересекает каждую дочернюю категорию, что, очевидно, вызывает огромный выбор.Я ищу способ загружать только требуемые дочерние категории или иным образом содержать его в одном цикле.

Я читал этот пост , но на самом деле он не предлагаетрешение, насколько я вижу.

Есть идеи?

http://samscode.com/index.php/2010/01/eager-fetch-multiple-child-collections-in-1-round-trip-with-nhibernate/

1 Ответ

1 голос
/ 05 апреля 2011

Вы можете использовать HQL для загрузки нескольких дочерних уровней.

var categoriesQuery = session.CreateQuery(@"select cat from Category cat join fetch cat.Children subCat join fetch subCat.Children").Future<Catgory>();

categoriesQuery.ToList(); // exec

Одним из предостережений этого подхода является то, что NH верен результату базы данных, поэтому вы получите дубликаты во внешних списках, если они не сопоставлены с AsSet.

Если это не так, вы можете выполнить каждый запрос отдельно, используя будущий метод. Они все еще будут упакованы.

...