2011-04-21 54 views
1

我有一個應用程序,有一個對象,例如具有每個人的自定義屬性的小列表的人員。這個集合通過nhibernate懶惰地加載,9/10次它只能爲一個人裝載,而不是IList。NHibernate的 - 加載100.000記錄每個與一個小的懶加載集合

這1/10,雖然我需要做一個導出到Excel數據庫中的所有的人,我需要包括它們的自定義屬性。因此,如果我對此正確(並在下面給出映射),nhibernate將針對100.000記錄和100.000查詢爲其自定義屬性發出1個查詢。

有什麼辦法發出2個查詢 - 1的記錄和1對所有的自定義屬性 - 並且NHibernate的創建正確的對象?或者可能只是爲了避免這種N + 1問題?

底層的數據庫是SQL Server 2008和應用程序是一個ASP.NET MVC應用程序

Person的映射是

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> <class name="Core.Person, Core" table="people" optimistic-lock="none"> 

    <id name="ID" column="id" type="System.Guid" unsaved-value="00000000-0000-0000-0000-000000000000"> 
     <generator class="guid" /> 
    </id> 
    <many-to-one name="Company" column="company_id" not-null="true" fetch="join" /> 

    <property name="Name" column="name" type="String" /> 
    <property name="DoB" column="dob" type="DateTime" not-null="true" /> 

    <map name="CustomFields" lazy="true" table="custom_fields" cascade="all-delete-orphan"> 
     <key column="person_id" /> 
     <index column="name" type="System.String" /> 
     <element column="value" type="System.String" /> 
    </map> 
     </class> </hibernate-mapping> 

回答

1

如果在同一個會話中的對象應該是在執行這兩個查詢會話和NHibernate將在查詢數據庫之前檢查緩存,因此它會從緩存中提取項目。

所以執行兩個查詢,一個裝載100個人的對象,一個加載所有孩子的自定義屬性的對象。

然後你使用根對象嗎?爲了驗證這一點,您可以使用SQL Server分析器來觀察正在執行的SQL查詢。

+0

此,如果您啓用查詢第二級緩存是唯一的真。如果你不這樣做,NHibernate仍然會向db發出查詢,然後檢查緩存並給你緩存的對象。 – Vadim 2011-04-21 14:06:40

1

爲了提高第二個事件中,我會建議兩件事情表現。首先,如果可能的話,我會使用IStatelessSession來獲取所有對象。這將繞過任何緩存並提高性能。

但最重要的,你需要修改查詢並做屬性的預先抓取。這樣你可以在一個查詢中獲得所有內容。 http://www.nhforge.org/doc/nh/en/index.html#querycriteria-dynamicfetching

+0

+1使用無狀態會話和渴望提取而不是懶惰。 – Rippo 2011-04-21 15:07:23

+0

已經使用無狀態會話來獲取100.000對象所涉及的所有內容。但你會在每個查詢的基礎上做到這一點(所以有一個名爲ExportAll()的方法,這是用戶statelesssession和eager加載底層集合的唯一方法,另一種稱爲FindAll(int page,int items)的方法是更通用)或在IRepository 中有一個FindAll方法,並且實現類在FindAll中使用IStatelessSession? – Yannis 2011-04-21 19:39:43

+0

就實現細節而言,我通常喜歡將來自報表數據提供者的查詢分開。通常情況下,報告比常規查詢更復雜,需求更多。 – Vadim 2011-04-22 15:18:37