2011-05-12 67 views
1

我有一个模型,看起来像这样:NHibernate的自基准性能

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级加载此表现很糟糕。当运行profiler时,我注意到它正在为表中的每个值执行select语句以查找我想要查找的数据。有没有一种方法可以提高性能,以便在桌面上进行某种类型的连接?

回答

0

您是否一次需要整个数据结构?通常当我遇到这个问题时,我只是拿掉nHibernate的映射处理并自己处理它。创建一个名为getChildren()的类的方法,并让它在调用时运行查询。如果你想添加一个子记录,然后添加另一个名为addChild()的方法,并使用它自己的父ID进行实例化。

1

您可以使用batch-size来预取实例,这会显着减少查询次数。

映射(如果不知道它是流利的同时支持):

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

如果你有一个根属性,可以使整个树查询一次。

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( “批量大小”, “20”)

查询

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

实际上应该导致只有一个查询。不确定NH是否真的不为列表(ChildComponentAttributes)执行查询,但值得一试。

+0

你可以举一个例子,说明如何添加一个Root属性来允许你这样做?我很好奇。 (1) – 2011-05-12 12:48:39

0

您可以在查询时急切地获取层次结构。您可以通过在查询中使用热切获取选项来执行此操作:

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

直到您想要获取的级别。