NHIbernate“References”属性生成Select+1,即使外部连接正确

NHIbernate“References”属性生成Select+1,即使外部连接正确,nhibernate,fluent-nhibernate-mapping,Nhibernate,Fluent Nhibernate Mapping,好吧,我有点被NHibernate的问题难住了。混淆之处在于PasswordResetToken 首先,这里是映射: public ContactMap() { Table("Contact"); Id(x => x.ContactId, "ContactId").Unique().GeneratedBy.Increment(); Map(x => x.EmailAddress); ... Map

好吧,我有点被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意味着使用连接而不是子选择,因此没有任何理由显示对db的额外调用

运行一个正确的SQL查询,返回一个联系人所需的所有信息,如NHProf的屏幕截图所示。突出显示的查询不必担心不同的表名等-我已清理了上面的代码:

我不明白的是,为什么会生成并运行几十个单独的PasswordResetToken表选择??其中一个查询只为没有PasswordResetToken的每个联系人生成,即。第一个查询为这些列返回空值-不确定这与此有什么关系

联系人可能有或可能没有一些角色对此问题而言是多余的,同样,可能有或可能没有一个PasswordResetToken

数据库有点不可靠,外键很少。在本例中,Contact和PasswordResetToken之间的链接是一个简单的共享列EmailAddress

所有这些查询都是在运行ie上面的一行代码时生成的。该代码不在循环中

如果我丢失了任何信息,请告诉我

我应该在谷歌上搜索什么?

这是一个很好的选择。我会尝试让它只处理两个查询,尽管从bug报告中听起来这将是一个挑战

附加的测试表明,引用唯一属性而不是Id的多对一关联会导致select n+1问题。尽管第一条语句包含正确的联接,但在联接选择之后,将逐个获取所有关联的实体。在unique列中具有相同值的实体甚至会被多次提取

有趣的是,只有在引用 实体已在会话缓存中。如果不是,则不是 将创建其他select语句


今天我自己也打了这个!诡异的是,我刚刚投了错误的票,所以我们得到的越多,它被修复的机会就越大。谢谢杰米-我从来没有想到它是一个错误。