我有两个类:文件,申请人,我正在使用ActiveRecord 3.0 RC(NHibernate 3.1.0.4000)。
文件
[ActiveRecord("`File`", Lazy = true)]
public class File : TestProDb<File> {
[PrimaryKey("`Id`")]
public virtual long Id { get; private set; }
[Property("`Name`")]
public virtual string Name { get; set; }
[HasMany(Cascade = ManyRelationCascadeEnum.AllDeleteOrphan, Inverse = true, Lazy = true)]
public virtual IList<Applicant> Applicants { get; set; }
public File() {
this.Applicants = new List<Applicant>();
}
}
申请人
[ActiveRecord("`Applicant`", Lazy = true)]
public class Applicant : TestProDb<Applicant> {
[PrimaryKey("`Id`")]
public virtual long Id { get; private set; }
[Property("`Surname`")]
public virtual string Surname { get; set; }
[BelongsTo(Column = "IdFile", Lazy = FetchWhen.OnInvoke)]
public virtual File File { get; set; }
}
现在我想根据一些申请人标准选择文件。结果文件应包含急切加载申请人:
using (new SessionScope()) {
DetachedCriteria fileQuery = DetachedCriteria.For<File>();
fileQuery.SetResultTransformer(new DistinctRootEntityResultTransformer());
fileQuery.SetFetchMode("Applicants", NHibernate.FetchMode.Eager);
fileQuery.CreateCriteria("Applicants").Add(Expression.Like("Surname", "a", MatchMode.Anywhere));
IList<File> files = File.FindAll(fileQuery);
foreach (File file in files) {
foreach (Applicant applicant in file.Applicants) {
Console.WriteLine(applicant.Surname);
}
}
}
来自NHProof - 执行 FindAll 时的第一个查询:
SELECT this_.[Id] as Id1_0_1_,
this_.[Name] as Name2_0_1_,
applicant1_.[Id] as Id1_1_0_,
applicant1_.[Surname] as Surname2_1_0_,
applicant1_.IdFile as IdFile1_0_
FROM [File] this_
inner join [Applicant] applicant1_
on this_.[Id] = applicant1_.IdFile
WHERE applicant1_.[Surname] like '%a%' /* @p0 */
来自NHProof - 循环中的第二个查询 Console.WriteLine(applicant.Surname):
SELECT applicants0_.IdFile as IdFile1_,
applicants0_.[Id] as Id1_1_,
applicants0_.[Id] as Id1_1_0_,
applicants0_.[Surname] as Surname2_1_0_,
applicants0_.IdFile as IdFile1_0_
FROM [Applicant] applicants0_
WHERE applicants0_.IdFile = 1 /* @p0 */
为什么我会为每个申请人循环(第二个查询示例)获得额外的数据库往返?由于FetchMode.Eager,总共应该只有一个数据库查询。我对此完全感到困惑。我甚至尝试删除虚拟关键字并将所有延迟值设置为false。还是一样。这是一个错误吗?
答案 0 :(得分:1)
您正在获取其他请求,因为对于NHibernate来说,急切加载关联需要外部联接,但您在查询中有内部联接。要解决此问题,您需要指定:
JoinType.LeftOuterJoin
修改强>
NHibernate需要左连接的原因如下,请考虑以下代码:
DetachedCriteria fileQuery = DetachedCriteria.For<File>();
fileQuery.SetFetchMode("Applicants", NHibernate.FetchMode.Eager);
如果NHibernate在此处进行内部联接,那么没有申请者的文件将不会出现在查询结果中。那可能不是你所期望的。
但是当您对申请人名称创建限制时,您肯定不希望申请人为空的文件。这允许NHibernate稍微优化查询,但禁用延迟加载。