2011-04-21 34 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