Nhibernate сам эталон производительности - PullRequest
1 голос
/ 12 мая 2011

У меня есть модель, которая выглядит следующим образом:

public class ComponentAttributeDto
{
    public virtual long ComponentAttributeId { get; set; }
    public virtual ComponentAttributeDto ParentComponentAttributeDto { get; set; }
    public virtual string ComponentAttributeName { get; set; }
    public virtual string Value { get; set; }
    public virtual DataType DataType { get; set; }
    public virtual IList<ComponentAttributeDto> ChildComponentAttributes { get; set; }
}

С файлом сопоставления:

public class ComponentAttributeMapping : ClassMap<ComponentAttributeDto>
{
    public ComponentAttributeMapping()
    {
        Table("ComponentAttributes");

        Id(x => x.ComponentAttributeId)
            .GeneratedBy.Identity();

        References(x => x.ParentComponentAttributeDto)
            .Column("ParentComponentAttributeId");

        HasMany(x => x.ChildComponentAttributes)
            .Fetch.Select()
            .Inverse()
            .Cascade.AllDeleteOrphan()
            .KeyColumn("ParentComponentAttributeId");

        Map(x => x.ComponentAttributeName)
            .Length(50);

        Map(x => x.Value)
            .Length(1500);

        Map(x => x.DataType)
            .Length(20);
    }
}

При загрузке этого большого набора данных, который имеет глубину примерно 4 уровня,производительность ужаснаПри запуске профилировщика я заметил, что он выполняет оператор выбора для каждого отдельного значения в таблице для данных, которые я хочу найти.Есть ли способ улучшить производительность, чтобы выполнить какое-либо соединение на столе или что-то еще?

Ответы [ 3 ]

1 голос
/ 12 мая 2011

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

отображение (не уверено, поддерживается ли оно пока Fluent):

HasMany(x => x.ChildComponentAttributes)
            .Fetch.Select()
            .SetAttribute("batch-size", "20")
            .Inverse()
            .Cascade.AllDeleteOrphan()
            .KeyColumn("ParentComponentAttributeId");

Если у вас есть свойство Root, вы можете сделать запрос для всего дерева сразу.

public class ComponentAttributeDto
{
  public virtual ComponentAttributeDto ParentComponentAttributeDto { get; private set; }
  public virtual ComponentAttributeDto Root 
  { 
     get 
     {
       if (ParentComponentAttributeDto == null) 
       {
         return this;
       }
       else 
       {
         return ParentComponentAttributeDto.Root;
       }
     }
     private set
     { /* just for NH to call it */ }
  }
  // ....
}

HasMany (x => x.Children) .AsSet (). SetAttribute ("batch-size "," 20 ")

запрос

session.CreateQuery(
@"from ComponentAttributeDto
where Root = :root"
  .SetEntity(root);

должен фактически приводить только к одному запросу.Не уверен, что NH на самом деле не выполняет запросы для списков (ChildComponentAttributes), но стоит попробовать.

0 голосов
/ 12 мая 2011

Вы можете охотно получить иерархию при запросе.Вы можете сделать это, используя опцию eager fetch в вашем запросе:

Session.QueryOver<ComponentAttributeDto>
       .Fetch(a => a.ChildComponentAttributes).Eager

Вниз до уровня, который вы хотите получить.

0 голосов
/ 12 мая 2011

Вам нужна вся структура данных одновременно? Обычно, когда я сталкиваюсь с этой проблемой, я просто убираю обработку отображения из nHibernate и разбираюсь с ней сам. Создайте метод для класса getChildren () и выполните его при вызове. Если вы хотите добавить дочернюю запись, добавьте еще один метод с именем addChild () и создайте его экземпляр с собственным родительским идентификатором.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...