如何按孙属性对 LINQ / 实体框架查询进行排序



我在使用 LINQ 查询时遇到了问题。我有以下数据结构(映射到 SQL Server DB 的实体框架类(:

Event具有 EventBlocks 属性,其中 0 个或多个 EventBlock 对象作为子对象。 EventBlock 具有 Details 属性,其中 0 个或多个 EventBlockDetail 对象作为子对象。 EventBlockDetail 有一个 DetailDate 和一个 StartTime。

我需要在网站上显示接下来的 3 个即将发生的事件。排序顺序由事件的最早开始日期和时间确定,该日期和时间存储在 Event -> EventBlock -> EventBlockDetail 中。如果接下来的 2 或 3 个即将到来的 EventBlockDetails 恰好属于同一事件,则该事件应仅显示一次,另一个事件应显示在前 3 名中。

有没有办法通过单个 LINQ 查询来实现这一点,这样我就不必在从数据库获取所有事件数据后进行大量循环和比较?

为了说明我正在尝试做什么,这是一个虚构的查询,它显然不起作用,因为第一个 OrderBy 不知道要按哪个属性排序。

var result = this.Context.Events.Where(
e => e.WebsiteId == websiteId && 
e.EventBlocks.All(
b => b.Details.All(
d => d.DetailDate >= DateTime.Now
)
)
).OrderBy( 
e => e.EventBlocks.OrderBy(
b => eb.Details.Min(d => d.DetailDate)).ThenBy(
b => eb.Details.Min(d => d.StartTime))
).Take(nrOfEvents).ToList();

您应该能够通过按日期和时间对所有事件详细信息进行排序并获取第一个事件来选择事件以及最早的日期和时间。 然后,您可以使用该详细信息对事件进行筛选和排序。

var result = Context.Events
.Where(e => e.WebsiteId == websiteId)
.Select(e => new 
{ 
Event = e, 
StartDetails = e.EventBlocks
.SelectMany(b => b.Details)
.OrderBy(d => d.DetailDate) 
.ThenBy(d => d.StartTime)
.FirstOrDefault()
})
.Where(x => x.StartDetails.DetailDate >= DateTime.Now)
.OrderBy(x => x.StartDetails.DetailDate)
.ThenBy(x => x.StartDetails.StartTime)
.Take(nrOfEvents)
.Select(x => x.Event)
.ToList();

请注意,如果DetailDate时间被截断,x => x.StartDetails.DetailDate >= DateTime.Now筛选器可能会删除尚未启动的内容。 在这种情况下,您可能实际上希望筛选DateTime.Today但如果日期是今天,则还要筛选时间是否早于当前时间。 例如,如果详细信息的日期为 2019-09-25(可能存储为午夜(,则与 2019-09-25 上午 8 点(如果这是当前日期时间(进行比较,即使详细信息的开始时间在上午 8 点之后,也会失败。

因此,也许该过滤器应该是以下内容,假设StartTime是基于任何StartTimeTimespan或类似的东西。

.Where(x => x.StartDetails.DetailDate > DateTime.Today ||
(x.StartDetails.DetailDate == DateTime.Today &&
x.StartDetails.StartTime >= DateTime.Now.TimeOfDay))

如果日期和时间存储在一列而不是两列中,这将更有意义,并且是一个更简单的查询。

最新更新