Как мы можем уменьшить накладные расходы прокси-сервера в NHibernate?

Мы используем Fluent NHibernate 1.3.0.727 и NHibernate 3.3.0.4000 для сопоставления наших свойств со столбцами в базе данных. Вот сокращенный образец одного из наших классов:

    public class TankMap : ClassMap<Tank>
    {
        public TankMap()
        {
            Id(o => o.Id);
            Map(o => o.TankSystem);
        }
    }

В этом случае свойство TankSystem является строкой.

В некоторых частях нашего приложения есть много вычислений, которые включают доступ к сопоставленным свойствам (таким как TankSystem) много раз. Когда мы профилируем приложение, простой доступ к этим свойствам занимает значительное время, потому что каждый раз, когда к ним обращаются, оно должно проходить через метод NHibernate.Proxy.DefaultLazyInitializer.Intercept.

Мы должны сделать наши вычисления максимально быстрыми и хотели бы избежать этих издержек при прокси. Один из подходов состоит в том, чтобы скопировать нужные нам свойства (например, TankSystem) в массивы и использовать массивы всякий раз, когда мы хотим получить доступ к этой информации, но тогда это не очень объектно-ориентированный подход.

Обновить:

Мы попытались отобразить наши свойства, используя Not.LazyLoad, например:

Map(o => o.TankSystem).Not.LazyLoad();

Однако это, похоже, не влияет на то, действительно ли это свойство проксируется.

Есть ли какая-либо опция, чтобы избежать / уменьшить издержки прокси?

3 ответа

Я действительно был бы осторожен с использованием.Not.LazyLoad() в ваших отображениях и довольно активно загружал ваши запросы по мере необходимости. Проблемы могут возникать, если стратегии выборки lazyload неправильно настроены. Всегда лучше проверять каждый запрос с помощью такого инструмента, как NHProf.

Linq:

var tanks = _session.Linq<Tank>()
               .Fetch(x=>x.TankSystem)
               .ToList();

QueryOver (мой префект): var tanks = _session.QueryOver() .Fetch(x=>x.TankSystem).Eager .List();

TankSystem tankSystemAlias = null;
var tanks = _session.QueryOver<Tank>()
                .JoinAlias(x=>x.TankSystem, () => tankSystemAlias, JoinType.InnerJoin) // or JoinType.LeftOuterJoin
                .List()

Да! .Not.LazyLoad() для спасения!

    public TankMap()
    {
        Id(o => o.Id);
        Map(o => o.TankSystem).Not.LazyLoad();
    }

Я нашел хорошее и краткое объяснение по этому поводу:

Вы можете спросить, что означает Not.LazyLoad(). По умолчанию Fluent NHibernate определяет сопоставления для использования отложенной загрузки. Но это также означает, что все свойства наших объектов должны быть виртуальными (прокси).

источник

Один из способов избежать виртуальных свойств объекта:

public TankMap()
{
        Id(o => o.Id);
        this.Not.LazyLoad(); 
        Map(o => o.TankSystem);
}

Таким образом, нет свойства прокси магии.

Другие вопросы по тегам