我有以下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语句来执行此操作。
答案 0 :(得分: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命名空间中的LINQ Query<T>
类内置的NHibernate进行的典型热切加载看起来像这样:
var results = new session.Query<WriteOffApprovalUser>()
.Fetch( x => x.Employee ) // This will tell NHibernate to perform a JOIN to the Employee table
.ToList();