在开始和结束日期时间过滤(预订)项目
Posted
技术标签:
【中文标题】在开始和结束日期时间过滤(预订)项目【英文标题】: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,但似乎找不到答案。
提前致谢!
【问题讨论】:
请提供足够的代码,以便其他人更好地理解或重现问题。 【参考方案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();
【讨论】:
以上是关于在开始和结束日期时间过滤(预订)项目的主要内容,如果未能解决你的问题,请参考以下文章