gpt4 book ai didi

nhibernate - 为什么 NHibernate 不急切地获取我的数据

转载 作者:行者123 更新时间:2023-12-02 08:53:22 25 4
gpt4 key购买 nike

我正在使用 Nhibernate 作为我的 ORM。

我有一个“Control”类,它与 ControlDetail 具有一对多关系(即一个控件有许多 controlDetails)。

在控件 xml 配置中,它具有以下内容

<bag name="ControlDetails" lazy="true" access="property" order-by="SortOrder asc"  cascade="all-delete-orphan" 
table="ControlDetail">
<key column="ControlID"/>
<one-to-many class="ControlDetail"/>
</bag>

这样我相信除非另有说明,否则它会延迟加载控件的 controldetails。

我正在运行 NProf 来尝试修复我们遇到的一些性能问题,它已识别出围绕这些类的 Select N + 1 问题。

我们正在使用存储库 DA 层,我尝试看看是否可以添加一种在需要时急切地获取数据的方法,并提出了这个。

public T GetById<T>(Int32 id, List<string> fetch) where T : BaseObject
{
T retObj = null;
ISession session = EnsureCurrentSession();
{
ICriteria criteria = session.CreateCriteria(typeof (T));
criteria.SetCacheable(true);
criteria.Add(Expression.Eq("Id", id));

foreach(var toFetch in fetch)
{
criteria.SetFetchMode(toFetch, FetchMode.Eager);
}

retObj = criteria.List<T>().FirstOrDefault();
}

return retObj;
}

*注意:我不喜欢存储库的设置方式,但它是在我参与该项目之前完成的,因此我们现在必须坚持这种模式。

我这样称呼这个方法

public Control GetByIDWithDetail(int controlID)
{
return DataRepository.Instance.GetById<Control>(controlID, new List<string>() {"ControlDetail"});
}

当我调试 GetByID 方法并查看 retObj 时,我可以看到 ControlDetails 列表已被填充(尽管奇怪的是,我也注意到没有 setfetchmode 设置列表正在被填充)

即使进行了此修复,NHProf 仍通过以下行识别出 Select N+1 问题

List<ControlDetail> details = control.ControlDetails.ToList();

我到底错过了什么以及如何停止这个 N+1 但仍然迭代 controlDetails 列表

编辑:xml 配置看起来像这样(稍微编辑以使其更小)

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DomainObjects" assembly="DomainObjects">
<class name="Control" lazy="false" table="Control" optimistic-lock="version" select-before-update="true" >
<id name="Id" type="int" column="ControlID" access="property">
<generator class="native" />
</id>
<version name="Version" column="Version" />
<property name="AdministrativeControl" column="AdministrativeControl" access="property" not-null="true" />
<property name="Description" column="ControlDescription" access="property" />
<property name="Title" column="Title" access="property" />
<property name="CountOfChildControls" access="property" formula="(select count(*) from Control where Control.ParentControlID = ControlID)" />

<bag name="ControlDetails" lazy="true" access="property" order-by="SortOrder asc" cascade="all-delete-orphan"
table="ControlDetail">
<key column="ControlID" />
<one-to-many class="ControlDetail" />
</bag>

</class>
</hibernate-mapping>

还有这个

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DomainObjects" assembly="DomainObjects">
<class name="ControlDetail" lazy="false" table="ControlDetail" select-before-update="true" optimistic-lock="version">
<id name="Id" type="int" column="ControlDetailID" access="property">
<generator class="native" />
</id>
<version name="Version" column="Version" />
<property name="Description" column="Description" access="property" not-null="true" />
<property name="Title" column="Title" access="property" />

<many-to-one name="Control" lazy="false" class="Control" column="ControlID" access="property"/>
</class>
</hibernate-mapping>

最佳答案

急切获取和急切加载之间存在显着差异。获取的意思是:放入同一个查询中。它有几个副作用并且可能会破坏它。急切加载是指强制NH立即加载,而不是等到第一次访问时才加载。它仍然使用额外的查询来加载,这导致了 N+1 问题。

NH 可能不会急切地获取,因为该属性称为 ControlDetails,但您将 ControlDetail 作为参数传递。

另一方面,这并不是避免 N+1 问题的好方法。请改用批量大小。它对应用程序完全透明,并按给定因子减少查询量(5 到 50 之间的值有意义,如果您不知道使用什么,请使用 10)。

关于nhibernate - 为什么 NHibernate 不急切地获取我的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6922444/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com