NHIbernate“引用”属性生成选择+ 1即使正确连接也是如此

时间:2013-03-20 14:29:02

标签: nhibernate fluent-nhibernate-mapping

好的,我对这个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,因此没有任何理由可以对数据库进行额外调用。

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

NHProf

我不明白为什么在地球上生成并运行几十个单独的选择到PasswordResetToken表?其中一个查询仅为没有PasswordResetToken的每个联系人生成(即第一个查询为这些列返回空值) - 不确定这与它有什么关系。

联系人可能有也可能没有几个角色(这个问题多余),同样,可能有也可能没有一个PasswordResetToken。

数据库有点狡猾,几乎没有外键。在这种情况下,Contact和PasswordResetToken之间的链接是一个简单的共享列“EmailAddress”。

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

如果我遗漏任何信息,请告诉我。

我应该用谷歌搜索什么?

1 个答案:

答案 0 :(得分:3)

这是一个bug。我会试着让它只用两个查询,虽然从错误报告中听起来这将是一个挑战。

  

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

     

有趣的是,只有引用时才会出现此错误   实体已经在会话缓存中。如果他们不是,不   创建了其他选择语句。