将date与datenow比较时,EF Core Where子句引发异常

时间:2019-10-11 19:22:57

标签: c# .net-core ef-core-3.0

我有一个查询方法,该方法应该给我从今天到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

1 个答案:

答案 0 :(得分: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,这就是为什么您看到该错误的原因。

您是否有任何原因无法在客户端上计算出“有效”日期,然后仅让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));