【问题标题】:nhibernate and "NOT IN" in a aggregate subquery聚合子查询中的休眠和“NOT IN”
【发布时间】:2011-05-19 16:15:34
【问题描述】:

我有一个实体 Reminder,其中包含 ReminderSchedule 的集合。 这是我的映射:

<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="Reminder" table="Reminders">
    <id name="Code" type="System.Guid">
        <column name="ReminderCode" />
        <generator class="guid.comb" />
    </id>
    ...
    <set access="field.pascalcase-underscore" cascade="all-delete-orphan" inverse="true" lazy="false" name="Schedules" mutable="true">
      <key foreign-key="FK_Schedules_Reminders">
        <column name="ReminderCode" />
      </key>
      <one-to-many class="ReminderSchedule" />
    </set>
</class>

这是实体ReminderSchedule的映射:

  <class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="ReminderSchedule" table="ReminderSchedules">
    <id name="Code" type="System.Guid">
      <column name="ReminderScheduleCode" />
      <generator class="guid.comb" />
    </id>
    <property name="NextSchedule" type="System.DateTime">
      <column name="NextSchedule" index="ReminderScheduleK01" not-null="true" />
    </property>
    <many-to-one class="Reminder" foreign-key="FK_ReminderScheduleToReminder" name="Reminder">
      <column name="ReminderCode" index="ReminderScheduleK02" not-null="true" />
    </many-to-one>
  </class>

ReminderSchedules 表包含与提醒关联的每个新计划的记录。 我可以关闭一个时间表 (Closed = 1) 并重新安排一个新的时间表。
在这种情况下,我将有一个 Closed = 0 的新记录,并且 NextSchedule 字段将包含下一个计划的日期/时间。

我已经在使用 CreateCriteria 来过滤提醒,而且效果非常好。 现在我想获取没有打开任何 ReminderSchedule 的提醒。

我已经想出了如何通过查询来做到这一点:

SELECT * FROM Reminders
WHERE ReminderCode 
    NOT IN (
        SELECT LastReschedule.ReminderCode FROM (
        SELECT ReminderCode, MAX(NextSchedule) MaxSchedule
        FROM ReminderSchedules
        WHERE Closed = 1 
        GROUP BY ReminderCode) LastReschedule
        )
ORDER BY Reminders.ReminderCode

但我不知道如何将其转换为适用于 nhibernate 的标准。

有没有人可以帮助我?将不胜感激。

【问题讨论】:

  • 这是 nhibernate 版本 2 还是 3?
  • @Rippo:我正在使用 NH 3.0.0.4000。

标签: nhibernate subquery criteria


【解决方案1】:

由于我无法使用 2 个子查询(嵌套),我尝试仅使用一个子查询来简化。
我已经为关闭的时间表获取了提醒的 ID (Schedules.Reminder.Code)。对我来说幸运的是,如果前一个没有关闭,我就不应该有另一个时间表。如果发生了,太糟糕了,我将无法管理它。

这是我能做的最好的:

ICriteria FiltersCriteria = Session.CreateCriteria<Domain.Reminder>("Reminders");

DetachedCriteria dCriteria = DetachedCriteria.For<Domain.ReminderSchedule>("Schedules")
    .SetProjection(Projections.ProjectionList()
    .Add(Projections.GroupProperty("Schedules.Reminder.Code")))
    // .Add(Projections.Max("Schedules.NextSchedule").As("MaxSchedule")))
    .Add(Restrictions.Eq("Schedules.Closed", true));

FiltersCriteria.Add(Subqueries.PropertyIn("Reminders.Code", dCriteria));  

我猜这个示例代码是不言自明的。
我为子查询使用了 DetachedCriteria,并将它用作我的 Criteria 的参数。

【讨论】:

    【解决方案2】:

    您可以通过使用Subquery 来实现。
    在 HQL 中,它应该类似于(未经测试):

    from Reminders as R
    where R.ReminderCode not in
       ( select RS.ReminderCode
         from ReminderSchedules as RS
         where RS.NextSchedule = (select max(NextSchedule) from ReminderSchedules as Inner where RS.Closed = 1)
       )
    

    尽管我不相信我完全满足了您的需求,但提供的链接应该可以帮助您找到正确的方向。

    【讨论】:

    • @sJhonny:感谢您的回答。我希望找到非 HQL 的东西。
    • @LeftyX:基本上,可以用HQL写的任何东西都可以写成Criteria;它只是不那么直观(至少在我看来)。关于查询 API-AFAIK,它还没有涵盖所有内容,不确定它是否适用于您的案例。
    • @sJhonny:是的,我可以理解。HQL 更容易,但我使用了 Criteria,希望我能做所有事情。实际上,我快到了。我必须稍微简化我的查询但我已经实现了我想要的(几乎)。我会尽快发布我的解决方案。
    • @LeftyX:你当然可以。正如我所说-AFAIK 标准等同于 HQL,因此您可以在 HQL 中编写的任何内容都可以在标准中编写。我自己不是 Criteria 方面最伟大的专家(我更喜欢尽可能使用 Linq),但如果你愿意,我可以解决这个问题。让我知道你的进展如何。
    • @sJhonny:谢谢。我明天会放一些代码。我在网上找到了不同的示例并将一些东西放在一起。
    猜你喜欢
    • 1970-01-01
    • 2012-09-06
    • 2015-06-14
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多