【问题标题】:LINQ Where clause inline for loop?LINQ Where 子句内联 for 循环?
【发布时间】:2015-07-07 14:37:38
【问题描述】:

我有名为 start 和 length 的数据库值。

start 是预订的开始时间(1->09:00、2->10:00 等),length 是以小时为单位的长度。

然后我有一个开始时间和结束时间的数组。我希望能够检查每个开始和结束对是否已经预订。到目前为止,我认为如果开始时间相同,则已预订,或者如果结束时间相同,则也已预订。但如果开始和结束时间在比较时间之间,则返回未预订,为假。

我正在尝试编写一个 LINQ 查询来测试一个预订是否已经在数据库中。到目前为止我有

var proposedRequest = db.requests.Include(r => r.rooms);
proposedRequest = proposedRequest.Where(r => r.booked.Equals(1));
proposedRequest = proposedRequest.Where(r => r.roundID.Equals(roundID));
proposedRequest = proposedRequest.Where(r => r.day.Equals(day));

int[] startTimes = new int[length];
int[] endTimes = new int[length];
for(var q=0;q<length;q++)
{
    startTimes[q] = time + q;
    endTimes[q] = time + q + 1;
}
proposedRequest = proposedRequest.Where(s => startTimes.Contains(s.start) || endTimes.Contains(s.start+s.length));

现在,这仅适用于新预订与数据库中已有预订同时开始或同时结束的情况。这个不看下面的案例

数据库中有一条记录,开始 -> 2 和长度 ->3。

所以这个预订从 10:00->13:00 开始。

但假设我正在检查一个从 11:00 开始到 12 点结束的条目。由于开始和结束时间不匹配,它不会像已预订的那样返回。

解决这个问题的最佳方法是什么?

我认为合适的唯一方法是遍历我的 startTime 和 endTime 数组,并为每一对设置另一个子句,该子句会产生如下内容:

.Where((s => s.startTime<startTime[i] && (s.startTime + s.Length) > endTime[i]) || (s => s.startTime<startTime[i+1] && (s.startTime + s.Length) > endTime[i+1]))

但我认为这是不可能的。

【问题讨论】:

  • 这应该会有所帮助:stackoverflow.com/questions/325933/… 但是您没有将日期时间存储在日期时间字段中,这让您自己变得更加困难。
  • @RobertMcKee 他们正在构建的预订系统很奇怪,而且可以连续运行数周。这就是为什么我不能存储日期时间字段,以及为什么你的链接不能适用于我的问题。我简单地用整数表示天数。
  • 该链接仍然有效,david.s 在下面为您完成了转换。
  • 开始/结束时间总是在同一天同一轮,还是每次开始/结束时也会改变?
  • @RobertMcKee 总是在同一天和同一天

标签: c# linq entity-framework linq-to-entities where-clause


【解决方案1】:

基于this 的答案,如果(StartA &lt;= EndB) and (EndA &gt;= StartB),则两个范围重叠

在你的情况下:

StartA = s.start
EndA = s.start + s.length
StartB = time
EndB = time + length

所以你的最后一个条件应该是这样的:

proposedRequest = proposedRequest.Where(s => s.start <= time + length &&
                                             s.start + s.length >= time);

【讨论】:

  • 我的问题可能有点含糊。我在上面添加了更多细节。我有一组开始和结束时间。
  • @user2976358 所以你有时间数组(如int[] times)和长度数组(如int[] lengths)?
  • 上面代码中的我的 for 循环将预订分成一小时的间隔,因此从 2 开始到 3 结束。endTimes 数组实际上是无关紧要的,因为它只是 startTime 值 +1
  • @user2976358 但是为什么您需要将预订分成一小时的间隔?要检查新预订(按时间和长度给出)是否与现有预订重叠,上面的答案就足够了。
【解决方案2】:

这将返回具有您的 StartTime、EndTime 和一个表示是否已预订的布尔值的对象。

var proposedRequest = db.requests
    .Include(r => r.rooms)
    .Where(r => r.booked.Equals(1))
    .Where(r => r.roundID.Equals(roundID))
    .Where(r => r.day.Equals(day))
    .ToList();

//int[] startTimes = new int[length];
//int[] endTimes = new int[length];
//for(var q=0;q<length;q++)
//{
//    startTimes[q] = time + q;
//    endTimes[q] = time + q + 1;
//}
var times=Enumerable
   .Range(time,length)
   .Select(r=>
       new {
           StartTime=r,
           EndTime=r+1,
           Booked=proposedRequest.Any(pr=>pr.StartTime<=r && pr.StartTime+pr.Length>r)
           }).ToList();

【讨论】:

  • 虽然名字看起来很奇怪。 proposedRequest 不是提议的吗?这些是已经在数据库中的那些。不应该是alreadyBooked 或类似的吗?
  • proposedRequest 是对尚未预订的预订的请求。此功能的目的是获取所有房间(与每个预订相关联),以便我可以将它们从可选房间中删除。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
相关资源
最近更新 更多