在聚合子查询中使用nhibernate和“NOT IN”

时间:2011-05-19 16:15:35

标签: nhibernate subquery criteria

我有一个实体提醒,其中包含 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表包含与提醒相关的每个新情景的记录。 我可以关闭一个时间表(已关闭= 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有效的条件中翻译它。

有没有人可以帮助我?真的很感激。

2 个答案:

答案 0 :(得分:2)

由于我无法使用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 ,并将其用作标准的参数。

答案 1 :(得分:0)

您可以使用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)
   )

即使我不相信我完全你需要什么,所提供的链接应该可以帮助你朝着正确的方向前进。