2010-03-02 69 views
2

我正在使用實體框架的asp.net mvc。 我有一個開始字段,結束字段和roomid字段(稱爲SpaceConfigurationId)的約會列表,並希望查找已爲特定房間雙重預訂的約會列表。假設結束後總是在開始之後,這很好。使用實體框架重疊約會

有4例將使預約匹配:預約B開始之前任用B開始之後結束任用B之前結束

  • 任命

    1. 約會開始開始約會b開始後約會b結束結束約會b結束後
    2. 任命開始預約B開始任用b結束
    3. 約會結束後之前預約B開始之後開始任用b結束後任命B開始之前任命b結束前結束

    我想要滿足任何這些要求的約會列表。這似乎很簡單,但實際上是一個智力遊戲。我看了一下相交,但似乎沒有任何地方。 我有以下定義的變量,並想返回一個列表。

    IQueryable<Appointment> appointments = Repository.ReadAppointments(); 
    ... insert code here ... 
    return appointments.ToList(); 
    

    下面是一些SQL這實在是太慢了,但可能有助於勾勒問題

    select COUNT(*) 
    from appointment a 
        cross join appointment b 
    where 
        not a.Id = b.Id 
        AND 
        a.SpaceConfigurationId = b.SpaceConfigurationId 
        AND 
        (
         (a.StartedAt < b.StartedAt and a.EndedAt > b.StartedAt and a.EndedAt < b.EndedAt) 
         OR 
         (a.StartedAt > b.StartedAt and a.StartedAt < b.EndedAt and a.EndedAt > b.EndedAt) 
         OR 
         (a.StartedAt < b.StartedAt and a.EndedAt > b.EndedAt) 
         OR 
         (a.StartedAt > b.StartedAt and a.StartedAt < b.EndedAt and a.EndedAt > b.StartedAt and a.EndedAt < b.EndedAt) 
        ) 
    
  • 回答

    1
    1. 上SpaceConfigurationId和日期列定義索引。
    2. 有2種情況下,當約會不匹配:

      1. 在b之前結束。
      2. 當a開始後b。

    所以..

    select COUNT(*) 
    from appointment a 
    join appointment b 
    on 
        (not a.Id = b.Id) 
        AND 
        (a.SpaceConfigurationId = b.SpaceConfigurationId) 
        AND 
        NOT (a.EndetAt < b.StartedAt) 
        AND 
        NOT (a.StartedAt > b.EndetAt) 
    

    所以......

    repository.ReadAppointments().Where(a => repository.ReadAppointments(). 
        Any(b => 
         !(b.ID == a.ID) && 
         (a.SpaceConfigurationId == b.SpaceConfigurationId) && 
         !(a.EndetAt < b.StartedAt) && 
         !(a.StartedAt > b.EndetAt))). 
        Select(t => t.ID).ToList(); 
    

    它不會產生相同的SQL。它實際上使用EXISTS,但有適當的索引應該可以正常工作。