2011-05-12 60 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 

直到您想要獲取的級別。