【问题标题】:Filter (reservation) items on start and end DateTime在开始和结束日期时间过滤(预订)项目
【发布时间】:2021-12-09 02:26:06
【问题描述】:

我是 .NET-Core 和构建 API 的新手,但遇到了一个问题。 我正在制作一个(Android)应用程序,人们可以在其中计划活动/生日派对或其他东西。 用户可以在填写开始和结束日期/时间后检索可用(预先添加的)场地/位置列表。这是我卡住的部分。

在他们填写开始和结束日期后,我想要一份可用场地列表,仅显示他们所选时间段的可用场地。

我的 API 中有 2 个模型,一个“Venue”模型和一个“VenueReservation”模型。

Venue 模型有一个 ID、位置和名称。 VenueReservationModel 有一个 Id、venueId、startDateTime、endDateTime。

我可以使用或做什么来根据用户的 DateTime 输入(开始和结束 DateTime)检索可用场所?

我使用 Enumerable.Where 方法玩弄 LINQ,但似乎找不到答案。

提前致谢!

【问题讨论】:

  • 请提供足够的代码,以便其他人更好地理解或重现问题。

标签: c# linq .net-core


【解决方案1】:

所以你有这样的类:

class Venue
{
    public int Id {get; set;}
    public string Location {get; set;}
    public string Name {get; set;}
}

class VenueReservation
{
    public int Id {get; set;}
    public int VenueId {get; set;}             // foreign key to Venue
    public DateTime StartDateTime {get; set;}
    public DateTime EndDateTime {get; set;}
}

你有:

IQueryable<Venue> Venues => ...        // Probably DbSet<Venue>
IQueryable<VenueReservation> VenueReservations => ...

在他们填写开始和结束日期后,我想要一份可用场地列表,仅显示他们所选时间段的可用场地。

因此,您需要获取“具有零个或多个 VenueReservations 的场地”。一旦你得到它们,你就可以只保留那些在所选时间段内根本没有预订的场地。

通过他们的预订获取场地

通常要获得“具有零个或多个 VenueReservations 的场地”,我会使用 Queryable.GroupJoin。有人提到.net core 不支持 GroupJoin。在这种情况下,请使用左外连接,后跟 GroupBy:

var venuesWithTheirReservations = venues.GroupJoin(venueReservations,

    venue => venue.Id,                            // from every Venue take the Id
    venueReservation => venueReservation.VenueId, // from every Reservation take the foreign key

    (venue, reservationsForThisVenue) => new
    {
        Venue = venue,
        Reservations = reservationsForThisVenue,
    });

LINQ left outer join 后跟 GroupBy:

var venuesWithTheirReservations = from venue in venues
    join reservation in venueReservations
    on venue.Id equals reservation.VenueId into g
    from reservationForThisVenu in g.DefaultIfEmpty()
    select new
    {
        Venue = venue,
        Reservation = reservationForThisVenue,
    })
    .GroupBy(joinResult => joinResult.Venue,

    // parameter resultSelector: for every venue, and all reservations for this venue
    // make one new
    (venue, reservationsForThisVenue) => new
    {
        Venue = venue,
        Reservations = reservationsForThisVenue,
    });

只保留可用的场地

所以,现在您已经获得了场地,每个场地都有预订,您可以使用Queryable.Where 仅保留在时间段内根本没有预订的场地。

换句话说:任何保留都不应与时隙重叠。

  • 所有预订都应在时隙开始之前结束 (= 完整的预订在时间段之前)
  • 或在时隙结束后开始 (= 完整的预订在时间段之后。

我们不希望部分时间段内的预订

所以继续 LINQ:

DateTime timeSlotStart = ...
DateTime timeSlotEnd = ...

var availableVenues = venuesWithTheirReservations.Where(venue =>

    // every Reservation should end before timeSlotStart
    // OR start after the timeSlotEnd:
    venue.Reservations.All(reservation =>

        // end before timeSlotStart OR
        reservation.EndDateTime <= timeSlotStart ||

        // start after the timeSlotEnd:
        reservation.StartDatetime >= timeSlotEnd));

【讨论】:

  • 感谢您的解释!它帮助很大,这就是我正在寻找的。再次感谢!
【解决方案2】:

你可以这样做。

获取在开始和结束之间输入日期的预订

IEnumerable<VenueReservation> reservationsBetweenStartAndEnd = venueReservations
    .Where(x => inputDateTime > x.StartDateTime && inputDateTime < x.EndDateTime);

获取输入日期在开始和结束之外的预订

IEnumerable<VenueReservation> reservationsOutsideStartAndEnd = venueReservations
    .Where(x => inputDateTime < x.StartDateTime || inputDateTime > x.EndDateTime);

如果您想严格比较日期并减少小时和分钟,您可以简单地在 DateTime 上使用 .Date。

举个例子,你会这样做

IEnumerable<VenueReservation> reservationsBetweenStartAndEnd = venueReservations
    .Where(x => inputDateTime.Date > x.StartDateTime.Date && inputDateTime.Date < x.EndDateTime.Date);

【讨论】:

    【解决方案3】:

    还有

    List<VenueReservation> reservationsBetweenStartAndEnd = venueReservations
        .Where(x => inputDateTime.Date > x.StartDateTime.Date && inputDateTime.Date < x.EndDateTime.Date).toLis();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-18
      • 1970-01-01
      • 2021-09-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多