NHibernate一对一关系 [英] NHibernate One-To-One Relationship

查看:63
本文介绍了NHibernate一对一关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下域模型:

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映射

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.

This is the SQL it is generating, and I was expecting a JOIN instead.

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语句来做到这一点.

Now there are four rows in the database, and the right data is coming back, but I would not expect five separate SQL statements to do this.

推荐答案

您需要急于加载/获取Employee实体,以避免出现的行为(通常称为SELECT N + 1问题).为此,您有两个选择:

You need to eager load/fetch the Employee entity to avoid the behavior that you are seeing which is often referred to as the SELECT N+1 problem. In order to do this you have two options:

选项1.映射中的负载过早,意味着当您查询WriteOffApprovalUser实体时,它将始终执行对Employee表的JOIN.注意:这听起来像您想要的,但请谨慎行事,因为您将迫使与该实体合作的所有开发人员都受此设计决定的困扰,直到时间结束.您将不得不问自己,我是否想查询WriteOffApprovalUser表,并且执行对Employee表的JOIN操作.如果答案是肯定的,则不要在映射文件中强制进行紧急加载.

Option 1. Eager load in the mapping meaning when you query the WriteOffApprovalUser entity, it will always perform a JOIN to the Employee table. Note: This may sound like what you want but be cautious as you will force all developers who ever work with this entity to be stuck with this design decision until the end of time. You'll have to ask yourself, would I ever want to query the WriteOffApprovalUser table and not perform a JOIN to the Employee table. If the answer is yes, then don't force the eager loading in the mapping file.

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

To have the Employee automatically fetched, change your HasOne code in the mapping to look something like this:

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

选项2.在查询中执行快速加载.我注意到您正在使用某种T模式存储库,因此您可能必须对其进行修改以处理急切的加载.在NHibernate.Linq名称空间中,使用NHibernate内置的LINQ Query< T> 类进行典型的紧急加载是这样的:

Option 2. Perform the eager loading in the query. I noticed that you are using some kind of Repository of T pattern so you may have to modify it to handle eager loading. Typical eager loading using NHibernate's built in LINQ Query<T> class in the NHibernate.Linq namespace looks something like this:

var results = new session.Query<WriteOffApprovalUser>()
                    .Fetch( x => x.Employee ) // This will tell NHibernate to perform a JOIN to the Employee table
                    .ToList();

这篇关于NHibernate一对一关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆