ORMにNhibernateを使用しています。なぜNHibernateは私のデータを取り出すのですか
私は、ControlDetailと1対多の関係を持つ(つまり、コントロールには多くのcontrolDetailsがあります)クラス "Control"を持っています。制御XMLで
は、それがそうでなければ、それは怠惰な負荷だろうコントロールのcontroldetailsに語っていない限り、私は信じているように、次の
<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>
を持っているconfigを入力します。
私はNHProfを実行して、パフォーマンス上の問題を解決しています。これらのクラスの周りに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を見てみると不思議な私も設定はsetFetchModeずに気づいたが、私は(ControlDetailsリストが取り込まれていることがわかりますように、このメソッドを呼び出しますリストはこれでも修正NHProfと
は、次の行
List<ControlDetail> details = control.ControlDetails.ToList();
何exactlで選択N + 1問題を識別)が取り込まれていましたyは私が行方不明ですし、どのように私は、このN + 1を停止するが、それでもcontrolDetailsリスト上
EDITを繰り返すことができます: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>
「コントロール」は、最初のレベルのキャッシュから来ている可能性が高いですが、関係は、親とキャッシュされるように設定されていないため、遅延ロードされています。 NHProfを取得し、キャッシュヒット対クエリを見てください。 – Phill
nhprofは、クエリキャッシュヒット/ミス/プットカウントで0を示し、2番目のレベルのキャッシュヒット/ミス/プットカウントでも0を示します。これを修正するにはどうすればよいですか? –
ControlとControlDetailの両方で0ヒットですか?または単にControlDetail? – Phill