Мы сталкиваемся с проблемой взаимно-однозначного сопоставления. NHProf показывает «Выбор оповещения N + 1», «Изменение критериев для использования FetchMode.Join не решает проблему N + 1».Ниже приведены подробности.
Сведения о версии программного обеспечения: NH версия: 1.2 .net Версия: 3.5 БД: Oracle 11g Кэш второго уровня: включено
Файлы Hbm и сущности классов.
Описание: сущность 'Sample' может содержать 0 или 1 сущность 'Association'.У объекта «Association» есть ограничение внешнего ключа от объекта «Sample».
Sample.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHSample" namespace="NHSample">
<class name="Sample" table="SAMPLE" proxy="Sample"
polymorphism="explicit" >
<id name="Id" type="Decimal" unsaved-value="-1">
<column name="SA_ID" sql-type="NUMBER" not-null="true"
unique="true"/>
<generator class="sequence">
<param name="sequence">SA_ID_SEQ</param>
</generator>
</id>
<property name="SampleName" type="String">
<column name="SAMPLE_NAME" length="100" sql-type="VARCHAR2" not-
null="false"/>
</property>
<one-to-one name="Association" class="Association" property-
ref="SampleAssociated" cascade="all-delete-orphan"/>
</class>
</hibernate-mapping>
Sample.cs
namespace NHSample
{
public class Sample
{
public virtual decimal Id
{
get ;
set ;
}
public virtual string SampleName
{
get ;
set ;
}
public virtual Association Association
{
get ;
set ;
}
}
}
Association.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="NHSample" namespace="NHSample">
<class name="Association" table="ASSOCIATION">
<id name="Id" type="Decimal" unsaved-value="-1">
<column name="AS_ID" sql-type="NUMBER" not-null="true"
unique="true"/>
<generator class="sequence">
<param name="sequence">AS_ID_SEQ</param>
</generator>
</id>
<property name="AssociationName" type="String">
<column name="ASSOCIATION_NAME" length="100" sql-type="VARCHAR2" not-
null="false"/>
</property>
<many-to-one name="SampleAssociated" class="Sample">
<column name="SA_ID" sql-type="NUMBER" not-null="true"/>
</many-to-one>
</class>
</hibernate-mapping>
Association.cs
namespace NHSample
{
public class Association
{
public virtual decimal Id
{
get ;
set ;
}
public virtual string AssociationName
{
get ;
set ;
}
public virtual Sample SampleAssociated
{
get ;
set ;
}
}
}
Критерии БЕЗ FetchMode = Соединение, используемое для доступа к Образцу объекта:
class Program
{
static void Main(string[] args)
{
using (ISession session = SessionFactory.OpenSession())
{
var electedIds = new List<decimal>() { 1, 2, 3 };
ICriteria criteria =
session.CreateCriteria(typeof(Sample));
criteria.Add(Expression.In("Id", electedIds));
var list = criteria.List();
}
Console.ReadKey();
}
}
NHProf показал N + 1 предупреждение, когда Criteria.List () был выполнен.Ниже приведены SQL-отчеты, представленные NHProf.
- выписка № 1
SELECT this_.SA_ID as SA1_0_1_,
this_.SAMPLE_NAME as SAMPLE2_0_1_,
associatio2_.AS_ID as AS1_1_0_,
associatio2_.ASSOCIATION_NAME as ASSOCIAT2_1_0_,
associatio2_.SA_ID as SA3_1_0_
FROM SAMPLE this_
left outer join ASSOCIATION associatio2_
on this_.SA_ID = associatio2_.SA_ID
WHERE this_.SA_ID in (1 /* :p0 */,2 /* :p1 */,3 /* :p2 */)
- выписка № 2
SELECT associatio0_.AS_ID as AS1_1_0_,
associatio0_.ASSOCIATION_NAME as ASSOCIAT2_1_0_,
associatio0_.SA_ID as SA3_1_0_
FROM ASSOCIATION associatio0_
WHERE associatio0_.SA_ID = 1 /* :p0 */
- выписка № 3
SELECT associatio0_.AS_ID as AS1_1_0_,
associatio0_.ASSOCIATION_NAME as ASSOCIAT2_1_0_,
associatio0_.SA_ID as SA3_1_0_
FROM ASSOCIATION associatio0_
WHERE associatio0_.SA_ID = 2 /* :p0 */
-Заявление № 4
SELECT associatio0_.AS_ID as AS1_1_0_,
associatio0_.ASSOCIATION_NAME as ASSOCIAT2_1_0_,
associatio0_.SA_ID as SA3_1_0_
FROM ASSOCIATION associatio0_
WHERE associatio0_.SA_ID = 3 /* :p0 */
Использование веб-сайта NHProf предлагает изменение циртерии с помощью FETCHMODE.Join:
class Program
{
static void Main(string[] args)
{
using (ISession session = SessionFactory.OpenSession())
{
var electedIds = new List<decimal>() { 1, 2, 3 };
ICriteria criteria =
session.CreateCriteria(typeof(Sample));
criteria.SetFetchMode("Association", FetchMode.Join);
criteria.Add(Expression.In("Id", electedIds));
var listByIds = criteria.List();
}
Console.ReadKey();
}
}
NHProf по-прежнему отображает предупреждение N + 1, и далее следуют SQL-запросы.
- выписка № 1
SELECT this_.SA_ID as SA1_0_1_,
this_.SAMPLE_NAME as SAMPLE2_0_1_,
associatio2_.AS_ID as AS1_1_0_,
associatio2_.ASSOCIATION_NAME as ASSOCIAT2_1_0_,
associatio2_.SA_ID as SA3_1_0_
FROM SAMPLE this_
left outer join ASSOCIATION associatio2_
on this_.SA_ID = associatio2_.SA_ID
WHERE this_.SA_ID in (1 /* :p0 */,2 /* :p1 */,3 /* :p2 */)
- выписка № 2
SELECT associatio0_.AS_ID as AS1_1_0_,
associatio0_.ASSOCIATION_NAME as ASSOCIAT2_1_0_,
associatio0_.SA_ID as SA3_1_0_
FROM ASSOCIATION associatio0_
WHERE associatio0_.SA_ID = 1 /* :p0 */
- выписка № 3
SELECT associatio0_.AS_ID as AS1_1_0_,
associatio0_.ASSOCIATION_NAME as ASSOCIAT2_1_0_,
associatio0_.SA_ID as SA3_1_0_
FROM ASSOCIATION associatio0_
WHERE associatio0_.SA_ID = 2 /* :p0 */
-утверждение № 4
SELECT associatio0_.AS_ID as AS1_1_0_,
associatio0_.ASSOCIATION_NAME as ASSOCIAT2_1_0_,
associatio0_.SA_ID as SA3_1_0_
FROM ASSOCIATION associatio0_
WHERE associatio0_.SA_ID = 3 /* :p0 */
Любые мысли о том, как преодолеть эту дополнительную SQL-статистику и проблему N + 1 в этом сценарии.
Спасибо.