2

我有以下内容Domain Model(s)

public class WriteOffApprovalUser
{
    public virtual string UserName { get; set; }
    public virtual Employee Employee { get; set; }
}

public class Employee
{
    public virtual string EmployeeID { get; set; }
    public virtual string EmployeeStatusCode { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string PreferredName { get; set; }
    public virtual string JobTitle { get; set; }
    public virtual string Division { get; set; }
    public virtual string Department { get; set; }
    public virtual string Location { get; set; }
    public virtual string City { get; set; }
    public virtual string DeskLocation { get; set; }
    public virtual string MailID { get; set; }
    public virtual string Phone { get; set; }
    public virtual string Fax { get; set; }
    public virtual string SecCode { get; set; }
    public virtual string UserId { get; set; }
    public virtual string SupervisorID { get; set; }
}

这些是我的Fluent Mappings

public class WriteOffApprovalUserMap : ClassMap<WriteOffApprovalUser>
{
    public WriteOffApprovalUserMap()
    {
        //Schema("LEGAL");
        Table("WRITEOFF_APPROVAL_USER");

        Id(x => x.UserName).Column("USER_NAME");

        HasOne(x => x.Employee).PropertyRef("UserId");

    }
}

public class EmployeeMap : ClassMap<Employee>
{
    public EmployeeMap()
    {
        // Table Name
        //Schema("ADP_FEED_OWNER");
        Table("ADP_EMPLOYEE");

        // Primary Key
        Id(x => x.EmployeeID).Column("EMPLID");

        // Mappings
        Map(x => x.UserId).Column("USER_ID");
        Map(x => x.FirstName).Column("FIRST_NAME");
        Map(x => x.LastName).Column("LAST_NAME");
        Map(x => x.PreferredName).Column("PREFERRED_NAME");
    }
}

这是我的查询:

var results = new Repository<WriteOffApprovalUser>(session)
                    .Query()
                    .ToList();

这是它正在生成的 SQL,而我期待的是 JOIN。

select writeoffap0_.USER_NAME as USER1_1_ from WRITEOFF_APPROVAL_USER writeoffap0_
SELECT employee0_.EMPLID as EMPLID0_0_, employee0_.USER_ID as USER2_0_0_, employee0_.FIRST_NAME as FIRST3_0_0_, employee0_.LAST_NAME as LAST4_0_0_, employee0_.PREFERRED_NAME as PREFERRED5_0_0_ FROM ADP_EMPLOYEE employee0_ WHERE employee0_.EMPLID=:p0;
SELECT employee0_.EMPLID as EMPLID0_0_, employee0_.USER_ID as USER2_0_0_, employee0_.FIRST_NAME as FIRST3_0_0_, employee0_.LAST_NAME as LAST4_0_0_, employee0_.PREFERRED_NAME as PREFERRED5_0_0_ FROM ADP_EMPLOYEE employee0_ WHERE employee0_.EMPLID=:p0;
SELECT employee0_.EMPLID as EMPLID0_0_, employee0_.USER_ID as USER2_0_0_, employee0_.FIRST_NAME as FIRST3_0_0_, employee0_.LAST_NAME as LAST4_0_0_, employee0_.PREFERRED_NAME as PREFERRED5_0_0_ FROM ADP_EMPLOYEE employee0_ WHERE employee0_.EMPLID=:p0;
SELECT employee0_.EMPLID as EMPLID0_0_, employee0_.USER_ID as USER2_0_0_, employee0_.FIRST_NAME as FIRST3_0_0_, employee0_.LAST_NAME as LAST4_0_0_, employee0_.PREFERRED_NAME as PREFERRED5_0_0_ FROM ADP_EMPLOYEE employee0_ WHERE employee0_.EMPLID=:p0;

现在数据库中有四行,并且正确的数据正在返回,但我不希望有五个单独的 SQL 语句来执行此操作。

4

1 回答 1

1

您需要预先加载/获取 Employee 实体以避免您看到的行为,这通常被称为 SELECT N+1 问题。为此,您有两种选择:

选项 1.映射含义中的急切加载当您查询 WriteOffApprovalUser 实体时,它将始终对 Employee 表执行 JOIN。注意:这可能听起来像您想要的,但要小心,因为您将迫使所有使用此实体的开发人员坚持此设计决策,直到时间结束。您必须问自己,我是否想要查询 WriteOffApprovalUser 表而不是对 Employee 表执行 JOIN。如果答案是肯定的,那么不要在映射文件中强制加载。

要自动获取 Employee,请将映射中的 HasOne 代码更改为如下所示:

HasOne(x => x.Employee).PropertyRef("UserId").Not.LazyLoad().Fetch.Join();

选项 2.在查询中执行预先加载。我注意到您正在使用某种 T 模式的存储库,因此您可能必须对其进行修改以处理急切加载。在 NHibernate.Linq 命名空间中使用 NHibernate 的内置 LINQQuery<T>类的典型预加载看起来像这样:

var results = new session.Query<WriteOffApprovalUser>()
                    .Fetch( x => x.Employee ) // This will tell NHibernate to perform a JOIN to the Employee table
                    .ToList();
于 2013-03-29T00:55:00.283 回答