EF Core Where 子句在将日期与 datenow 进行比较时抛出异常

EF Core Where Clause throws Exception when Comparing date with datenow

我有一个查询方法,它应该给我从今天到 7 天的下一场比赛,给定联赛 ID。所以如果今天的日期是 2019-10-11 那么它应该给我所有的体育比赛直到 2019-10-18。

        public IQueryable<MatchDTO> GetMatchesForNextSevenDaysByLeagueAsync(int leagueId)
        {
            var todayDate = DateTime.Now;
            var matches = _context.Matches.Include(e => e.HomeTeam).Include(e => e.AwayTeam).Include(e => e.League).Where(m => m.LeagueId == leagueId).OrderBy(m => m.MatchDate).ThenBy(m => m.Time).Where(m => ((todayDate - m.MatchDate).Days) <=7).Select(m => DTOConverter.ConvertMatchToDTO(m));

            return matches;
        }

调用抛出异常:

"The LINQ expression 'Where<Match>(\r\n    source: 
ThenBy<Match, DateTime>(\r\n        source: OrderBy<Match, DateTime>(\r\n            
source: Where<Match>(\r\n                source: DbSet<Match>, \r\n                
predicate: (m) => m.LeagueId == (Unhandled parameter: __leagueId_0)), \r\n            
keySelector: (m) => m.MatchDate), \r\n        keySelector: (m) => m.Time), \r\n    
predicate: (m) => m.MatchDate - (Unhandled parameter: __todayDate_1).TotalDays <= 7)' 
could not be translated. Either rewrite the query in a form that can be translated, or 
switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), 
ToList(), or ToListAsync(). 
See https://go.microsoft.com/fwlink/?linkid=2101038 for more information."

对我来说,它看起来不喜欢我在 .Where(m => ((todayDate - m.MatchDate).Days) <=7)

中比较日期的方式

我尝试过使用客户端评估,但它太慢了。关于如何重写此代码以便代码正常工作的任何想法。

请注意,我使用的是 EF Core 3.0

如果不来回滚动,该行有点难以阅读,所以我希望您不介意我为了自己的方便而重新格式化它:

var matches = _context
    .Matches
    .Include(e => e.HomeTeam)
    .Include(e => e.AwayTeam)
    .Include(e => e.League)
    .AsQueryable()
    .Where(m => m.LeagueId == leagueId)
    .OrderBy(m => m.MatchDate)
    .ThenBy(m => m.Time)
    .Where(m => ((todayDate - m.MatchDate).Days) <=7)
    .Select(m => DTOConverter.ConvertMatchToDTO(m));

通读本文,我可以看到您的第二个 .Where 子句正在检查一个日期减去另一个日期的 .Days 属性 值。我怀疑 Entity Framework 能否将其转换为有效的 SQL 这就是您看到该错误的原因。

您是否有任何理由无法在客户端计算 "valid" 的日期,然后让 SQL 根据需要过滤行?例如:

.Where(m => m.MatchDate >= DateTime.Now && <= DateTime.Now.AddDays(7))

应该将其翻译成 TSQL BETWEEN 语句 - 这比尝试解析您存储的日期时间以获取日期部分并计算出它们是否是要好得多距给定日期的特定数字。

也就是说,您可能想查看一下您编写的一般查询。从您提供的代码片段中,我不太确定为什么 .AsQueryable 是必需的 - 您使用的扩展方法本机接受 IEnumerableIQueryable,因此您不必强制转换.

在您尝试对结果集进行排序之前,我还会结合这两个 where 子句。不确定 EF to SQL 是否在所有情况下都足够聪明来优化它,但它不会受到伤害!总之,您的最终查询应如下所示:

var matches = _context
    .Matches
    .Include(e => e.HomeTeam)
    .Include(e => e.AwayTeam)
    .Include(e => e.League)
    .Where(m => 
        m.LeagueId == leagueId 
        && m.MatchDate >= DateTime.Now && <= DateTime.Now.AddDays(7))
    .OrderBy(m => m.MatchDate)
    .ThenBy(m => m.Time)
    .Select(m => DTOConverter.ConvertMatchToDTO(m));