好的,我对这个 NHibernate 查询有点困惑。困惑在于 PasswordResetToken。
首先,这是映射:
public ContactMap()
{
Table("Contact");
Id(x => x.ContactId, "ContactId").Unique().GeneratedBy.Increment();
Map(x => x.EmailAddress);
...
Map(x => x.JobTitle);
References(x => x.PasswordResetToken, "EmailAddress")
.PropertyRef(x => x.EmailAddress)
.Cascade.None()
.Not.LazyLoad()
.Not.Update();
HasMany(x => x.Roles)
.Table("tblContactRole").KeyColumn("ContactId").Element("Role", part => part.Type<global::NHibernate.Type.EnumStringType<ContactRoles>>())
.AsSet()
.Not.LazyLoad();
}
现在这里是查询:
public IList<Contact> GetContacts(int id)
{
var contacts = Session.CreateCriteria<Contact>()
.Add(Restrictions.Eq("Id", id))
.Add(Restrictions.Eq("IsActive", true))
.SetFetchMode("Roles", FetchMode.Eager)
.SetFetchMode("PasswordResetToken", FetchMode.Eager)
.SetResultTransformer(CriteriaSpecification.DistinctRootEntity)
.List<Contact>();
return contacts;
}
我的理解是 FetchMode.Eager 意味着使用 JOIN 而不是 SUBSELECT,因此没有任何理由出现对 db 的额外调用。
运行正确的 SQL 查询,返回为联系人补充所需的所有信息,如 NHProf 的屏幕截图所示(突出显示的查询)(不要担心不同的表名等 - 我已经清理了上面的代码):
我不明白为什么会生成并运行对 PasswordResetToken 表的数十个单独选择?其中一个查询仅针对没有 PasswordResetToken 的每个联系人生成(即第一个查询为这些列返回空值) - 不确定这与它有什么关系。
一个联系人可能有也可能没有几个角色(对于这个问题是多余的),同样,可能有也可能没有一个 PasswordResetToken。
数据库有点狡猾,外键很少。在这种情况下,Contact 和 PasswordResetToken 之间的链接是一个简单的共享列“EmailAddress”。
所有这些查询都是在运行上面的那一行代码时生成的(即,该代码不在循环中)。
如果我遗漏任何信息,请告诉我。
我应该在谷歌上搜索什么?