我们如何减少NHibernate的属性代理开销?

时间:2012-05-02 17:50:41

标签: performance nhibernate fluent-nhibernate proxy castle-dynamicproxy

我们正在使用Fluent NHibernate 1.3.0.727和NHibernate 3.3.0.4000将我们的属性映射到数据库中的列。以下是我们的ClassMaps之一的缩写示例:

    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 个答案:

答案 0 :(得分:1)

是的! .Not.LazyLoad()救援!

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

我找到了一个简短的解释:

  

您可能想知道Not.LazyLoad()的含义。默认情况下,Fluent NHibernate定义使用延迟加载的映射。但这也意味着我们实体的所有属性都必须是虚拟的(代理)。

source

答案 1 :(得分:1)

我会非常小心在您的映射中使用.Not.LazyLoad(),并根据需要在您的查询中加载。如果未正确配置lazyload fetch策略,问题可能会增加。最好使用像NHProf这样的工具检查每个查询。

的LINQ:

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

QueryOver(我的首选):     var tanks = _session.QueryOver()                    .Fetch(X =&GT; x.TankSystem).Eager                    .LIST();

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

答案 2 :(得分:0)

避免在对象上使用虚拟属性的一种方法是:

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

这种方式没有属性代理魔法。