C# 使用实体框架的重叠任命

C# 使用实体框架的重叠任命,c#,asp.net,.net,asp.net-mvc,entity-framework,C#,Asp.net,.net,Asp.net Mvc,Entity Framework,我正在使用asp.NETMVC和实体框架。 我有一个带有startedat字段、endedat字段和roomid字段(称为SpaceConfigurationId)的约会列表,我想查找已为给定房间双重预订的约会列表。可以假设endedat总是在startedat之后 有4种情况允许匹配预约: 约会a在约会b开始之前开始,在约会b开始之后和约会b结束之前结束 约会a在约会b开始后和约会b结束前开始,在约会b结束后结束 约会a在约会b开始之前开始,在约会b结束之后结束 约会a在约会b开始之后和约会b

我正在使用asp.NETMVC和实体框架。 我有一个带有startedat字段、endedat字段和roomid字段(称为SpaceConfigurationId)的约会列表,我想查找已为给定房间双重预订的约会列表。可以假设endedat总是在startedat之后

有4种情况允许匹配预约:

  • 约会a在约会b开始之前开始,在约会b开始之后和约会b结束之前结束
  • 约会a在约会b开始后和约会b结束前开始,在约会b结束后结束
  • 约会a在约会b开始之前开始,在约会b结束之后结束
  • 约会a在约会b开始之后和约会b结束之前开始,在约会b开始之后和约会b结束之前结束
  • 我想要符合这些要求的任命名单。这看起来很简单,但实际上有点像智力游戏。我看了一下intersect,但似乎什么也没找到。 我定义了以下变量,希望返回一个列表

    IQueryable<Appointment> appointments = Repository.ReadAppointments();
    ... insert code here ...
    return appointments.ToList();
    
    IQueryable约会=Repository.readappoints();
    ... 在这里插入代码。。。
    返回约会。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)
        )
    
    选择计数(*)
    从预约
    交叉加入预约b
    哪里
    非a.Id=b.Id
    及
    a、 SpaceConfigurationId=b.SpaceConfigurationId
    及
    (
    (a.StartedAtb.StartedAt和a.EndedAtb.StartedAt和a.StartedAtb.EndedAt)
    或
    (a.StartedAtb.EndedAt)
    或
    (a.StartedAt>b.StartedAt和a.StartedAtb.StartedAt和a.EndedAt
  • 在SpaceConfigurationId和date列上定义索引
  • 约会不匹配时有两种情况:

  • 当a在b之前结束时
  • 当a在b之后开始时
  • 所以

    选择计数(*)
    从预约
    加入约会b
    在…上
    (非a.Id=b.Id)
    及
    (a.SpaceConfigurationId=b.SpaceConfigurationId)
    及
    不是(a.结束b.结束)
    
    所以

    repository.readappoinces()。其中(a=>repository.readappoinces()。
    任何(b=>
    !(b.ID==a.ID)和
    (a.SpaceConfigurationId==b.SpaceConfigurationId)&&
    !(a.结束b.结束)。
    选择(t=>t.ID).ToList();
    
    它不会生成相同的SQL。它实际上使用的是
    EXISTS
    ,但是使用适当的索引应该可以

    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();