如何使用NHibernate查询子集合到嵌套集合?

时间:2011-05-19 16:42:42

标签: .net nhibernate

鉴于以下结构:

public class Contract
{
  virtual int Id {get;set;}
  virtual IList<Course> Courses {get;set;}
}

public class Course
{
  virtual int Id {get;set;}
  virtual IList<Schedule> Schedules {get;set;}  
}

public class Schedule
{
  virtual int Id {get;set;}
  virtual DateTime Start {get;set;}
  virtual DateTime End {get;set;}
}

我需要查找给定的Contract是否有任何Schedule(请注意这是如何通过Course关系)匹配我的任何新Schedule对象集合数据库中的所有合同。

修改

我的主要问题是找出一种方法(如果可能且合理的话) 对一组时间表进行查询,而不只是一个 标量DateTime。这样,我想我会避免做个人 查询每个Schedule实例。例如,结构将是 类似的东西:

Contract contract = new  Contract 
{ 
  Courses = new List<Course>() 
  { 
    { 
      new List<Schedule>() 
      { 
        {new Schedule { Start = new DateTime(2011,01,01), End = new 
DateTime(2011,01,31) } }, 
        {new Schedule { Start = new DateTime(2011,02,01), End = new 
DateTime(2011,02,27) } }, 
        {new Schedule { Start = new DateTime(2011,03,01), End = new 
DateTime(2011,03,15) } } 
      } 
    }, 
    { 
      new List<Schedule>() 
      { 
        {new Schedule { Start = new DateTime(2010,12,12), End = new 
DateTime(2010,12,31) } } 
      } 
    } 
  } 
}; 

您认为有一种方法可以立即查询所有内容吗?是不是更好 只是做一个.NET foreach循环和单独查询?

提前致谢。

2 个答案:

答案 0 :(得分:0)

我不确定这是如何映射到LINQ to NHibernate的,但是HQL版本可以解决这个问题:

FROM Contract cn WHERE EXISTS 
    (FROM cn.Courses cc WHERE EXISTS 
        (FROM cc.Schedules s WHERE s.Start < '2011/01/01'))

假设有一个“Contracts”集合,LINQ-y解决方案可能看起来像:

Contracts.Where(cn => cn.Courses.Any(cc => cc.Schedules.Any(s => s.Start < ...)));

但我不知道LINQ提供程序是否正确转换。

答案 1 :(得分:0)

我通过递归遍历每一个来解决它。我不太关注几乎N + 1个查询的可能性,因为我的数据永远不会查询超过5次(tops)。我仍然给出了Rytmis的答案,因为他的HQL给了我使用Any的想法。

foreach (Course course in contract.Courses)
{
    foreach (Schedule entry in course.Schedules)
    {
        Schedule schedule = entry;
        var query = from  c in Session.Query<Course>()
                    where c.Schedules.Any(x =>
                                              x.Day == schedule.Day &&
                                              (
                                                (x.EndDate < schedule.EndDate && x.StartDate > schedule.StartDate) ||
                                                (x.EndDate == schedule.EndDate && x.StartDate > schedule.StartDate)
                                                // about 10 more of these
                                              )
                                          )
                     select c;

        var conflicting = query.FirstOrDefault();
        if (conflicting != null)
        {
            DoStuff()
        }
    }
}