Как я могу предварительно загрузить записи с родительскими и дочерними ссылками на себя с помощью Castle ActiveRecord?

Моя таблица SQL выглядит так:

CREATE TABLE Page (
    Id int primary key,
    ParentId int, -- refers to Page.Id
    Title varchar(255),
    Content ntext
)

и сопоставляется со следующим классом в моей модели ActiveRecord:

[ActiveRecord]
public class Page {

    [PrimaryKey]
    public int Id { get; set; }

    [BelongsTo("Parent")]
    public virtual Page Parent { get; set; }

    [Property]
    public string Title { get; set; }

    [Property]
    public string Content { get; set; }

    [HasMany(typeof(Page), "Parent", "Page")]
    public IList<Page> Children { get; set; }
}

Я использую ActiveRecord для получения корней дерева, используя следующий код:

var rootPages = new SimpleQuery<Page>(@"from Page p where p.Parent is null");
return(rootPages.Execute());

Это дает мне правильный граф объектов, но трассировка SQL Profiler показывает, что дочерние страницы загружаются отдельным запросом для каждого нелистового узла в дереве.

Как я могу заставить ActiveRecord загружать все сразу ("SELECT * FROM Page"), а затем отсортировать объекты в памяти, чтобы получить требуемые отношения родитель-потомок?


person Dylan Beattie    schedule 10.11.2008    source источник


Ответы (2)


Самый простой способ сделать это - получить всю таблицу, а затем отфильтровать результат. Это довольно просто, если вы используете linq.

var AllPages = ActiveRecordMediator<Page>.FindAll();
var rootPages = AllPages.Where(p => p.Parent == null);
person oillio    schedule 28.07.2010

Попробуй это:

var rootPages = new SimpleQuery<Page>(@"from Page p left join fetch p.Children where p.Parent is null");
return(rootPages.Execute());

Это приведет к тому, что коллекция Children каждой страницы в наборе результатов будет заполнена во время первоначального запроса, что должно уменьшить общую нагрузку на запрос до одного запроса.

person Neil Hewitt    schedule 14.11.2008
comment
Это загрузит только первый уровень детей. Любое дерево с глубиной больше 2 по-прежнему вызовет проблему N + 1. - person oillio; 28.07.2010
comment
Истинный. Но в примере вопрошающего нет второго уровня детей. Вам нужно будет разработать запрос, соответствующий конкретным обстоятельствам в каждом случае. AFAIK не существует универсального подхода. - person Neil Hewitt; 28.07.2010