NHibernate - 左连接

Posted

技术标签:

【中文标题】NHibernate - 左连接【英文标题】:NHibernate - Left joins 【发布时间】:2012-03-06 19:07:50 【问题描述】:

我有以下两张表:

工作 AreaID、JobNo(复合键)

日志 LogID、AreaID、JobNo

我需要获取所有没有与之关联的日志的作业。在 SQL 中我可以这样做:

SELECT Jobs.AreaID,
       Jobs.JobNo
FROM   Jobs
       LEFT JOIN Logs
           ON Jobs.AreaID = Logs.AreaID
           AND Jobs.JobNo = Logs.JobNo
WHERE  Logs.LogID is null

但我不确定如何使用 NHibernate 来实现这一点。有没有人可以指点一下?

这是我的映射:

<class name="Job" table="Jobs">
    <composite-key name="Id">
        <key-property name="JobNo"/>
        <key-many-to-one name="Area" class="Area" column="AreaID"/>
    </composite-key>
</class>

<class name="Log" table="Logs">
    <id name="Id" column="LogID">
        <generator class="identity"/>
    </id>
    <property name="JobNo"/>
    <many-to-one name="Area" class="Area" column="AreaID"/>
</class>

谢谢

更新

好的,我稍微修改了 Nosila 的答案,这就是我想要的:

Log logs = null;

return session.QueryOver<Job>()
    .Left.JoinAlias(x => x.Logs, () => logs)
    .Where(x => logs.Id == null)
    .List<Job>();

我还必须将此添加到我的工作映射中:

<bag name="Logs">
    <key>
        <column name="JobNo"></column>
        <column name="DivisionID"></column>
    </key>
    <one-to-many class="Log"/>
</bag>

感谢您的帮助。 :)

【问题讨论】:

您可以发布您现在的查询吗? 上面的SQL查询是我目前使用的。我现在正在学习 NH,并正在尝试将一个小型应用程序转换为使用它。 您是否创建了映射?另外,如果我错了,有人纠正我,但我认为您需要 NHibernate 3.2 才能为您的加入添加条件(无论如何使用QueryOver API)。 是的,我已经在上面包含了我的映射。 【参考方案1】:
Job job = null;
var jobsWithoutLogs = session.QueryOver(() => job)
    .WithSubquery.WhereNotExists(QueryOver.Of<Log>()
        .Where(log => log.Job == job)
        .Select(Projections.Id()))
    .List()

更新:我看到你添加了映射。以上代码仅适用于以下映射

<class name="Log" table="Logs">
    <id name="Id" column="LogID">
        <generator class="identity"/>
    </id>
    <many-to-one name="Job" >
      <column name="JobNo"/>
      <column name="AreaID"/>
    <many-to-one />
</class>

【讨论】:

不错。我更喜欢这个解决方案。 这似乎更容易,尽管我收到错误“无法在没有投影的条件下使用子查询”。此外,由于它使用子查询而不是简单的左连接,这是否会是一个更昂贵的查询? 1) 添加了投影。 2)我不认为它更贵,因为它做同样的事情。你可以检查查询计划 感谢您的建议,但我使用了 Nosila 的答案并稍作修改(请参阅我的第一篇文章)。 :)【参考方案2】:

我不熟悉复合标识符,因为我不使用它们,所以据我所知,NHibernate 会自动创建正确的左连接。尽管如此,下面的(未经测试的)查询应该可以帮助您入门。

Job jobAlias = null;
Log logAlias = null;
YourDto yourDto = null;

session.QueryOver<Job>()
    // Here is where we set what columns we want to project (e.g. select)
    .SelectList(x => x
        .Select(x => x.AreaID).WithAlias(() => jobAlias.AreaID)
        .Select(x => x.JobNo).WithAlias(() => jobAlias.JobNo)
    )
    .Left.JoinAlias(x => x.Logs, () => logAlias, x.JobNo == logAlias.JobNo)
    .Where(() => logAlias.LogID == null)
    // This is where NHibernate will transform what you have in your `SelectList()` to a list of objects
    .TransformUsing(Transformers.AliasToBean<YourDto>())
    .List<YourDto>();

public class YourDto

    public int AreaID  get; set; 
    public int JobNo  get; set; 

注意:您需要 NHibernate 3.2 才能设置连接条件。

【讨论】:

谢谢。我将不得不仔细考虑这一点(其中有一些错误)。如此简单的查询似乎也极其复杂。 @Tom 我同意复杂性,用 SQL 编写会简单得多。我觉得 ORM 抽象已经失控了。

以上是关于NHibernate - 左连接的主要内容,如果未能解决你的问题,请参考以下文章

NHibernate左连接选择计数在一对多关系中

您是不是会将 NHibernate 用于具有部分无法控制的遗留数据库的项目?

NHibernate 上升 NHibernate.HibernateException:找不到命名连接

NHibernate 和数据库连接故障转移?

错误的连接字符串NHibernate 3.3

流畅的 Nhibernate 内部连接