LINQ where 子句中的 DateTime 属性错误

我有一个非常简单的方法,它使用一些 LINQ 来访问我的数据库中的数据。


我有一些项目正在存储它们的创建日期。日期包括一个偏移量,因此它在数据库中存储为 datetimeoffset 类型。我正在尝试按日期过滤项目,为此我需要减去偏移时间来比较它们:


public async Task<IEnumerable<Item>> GetItems(DateTime? startDate)

{

    var items = _dbContext.Items                                

                        .AsQueryable();


    if (startDate != null)

    {

        items = items.Where(i =>

            i.DateCreated.DateTime.AddHours(i.DateCreated.Offset.Hours) >= startDate.Value);

    }


    return await items

                     .ToListAsync();

}

但是当ToListAsync()被调用时,我得到这个错误:


因警告“Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning:LINQ 表达式‘where ([e].DateCreated.DateTime.AddHours(Convert([e].DateCreated.Offset.Hours, Double)) >= __startDate_Value_0)”而生成错误不被翻译,将在当地进行评估。'。通过将事件 ID“RelationalEventId.QueryClientEvaluationWarning”传递给“DbContext.OnConfiguring”或“AddDbContext”中的“ConfigureWarnings”方法,可以抑制或记录此异常。


问题似乎出在AddHours方法上,如果我把它去掉,它就可以正常工作。但我不知道是否有办法在不使用该方法的情况下使它工作。


我可以在这里使用不同的策略吗?


尚方宝剑之说
浏览 101回答 2
2回答

翻翻过去那场雪

实际上支持DateTime.AddHours方法的翻译。问题是目前 EF Core 无法翻译 的大部分(如果不是全部)成员DateTimeOffset,在这种特殊情况下 -DateTime属性(与 等相同Offset)DateTimeUtc。幸运的是它确实支持DateTimeOffset比较的转换,所以解决方案是换一种方式——将DateTime参数转换为DateTimeOffset并在查询中进行简单的比较,例如if (startDate != null){&nbsp; &nbsp; // Note: must be a variable outside the query expression tree&nbsp; &nbsp; var startDateOffset = new DateTimeOffset(startDate.Value);&nbsp; &nbsp; items = items.Where(i => i.DateCreated >= startDateOffset);}

慕侠2389804

更新的答案(EF Core):根据此链接,DbFunctionsEF Core 当前不支持。如果您想AddHour使用 EF Core 进行调用,一种选择是AddHour在您的数据库中定义为标量函数,然后您可以在您的 LINQ 查询中调用它。本文档解释了如何完成:在您的 DbContext 上声明一个静态方法并使用以下注释对其进行注释DbFunctionAttribute:public class MyDbContext : DbContext{&nbsp; &nbsp; [DbFunction]&nbsp; &nbsp; public static int AddHours(DataTime source, int hours)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; // you don't need any implementation&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; throw new Exception();&nbsp;&nbsp; &nbsp; }}像这样的方法会自动注册。注册后,对 LINQ 查询中的方法的调用可以转换为 SQL 中的函数调用:items = items.Where(i =>&nbsp; &nbsp; MyDbContext.AddHours(i.DateCreated, i.DateCreated.Offset.Hours) >= startDate.Value);免责声明:我个人不喜欢这个解决方案。编写一个新方法,只是为了抛出一个异常,远不是一个优雅的设计。不幸的是,如果您想使用 EF Core,您没有太多选择。原始答案(EF 4/5/6):AddHour不是您数据库中的函数。它需要被翻译成数据库中相应的功能。如果您使用的是 SQL Server,那么您可以使用这段代码,它将转换AddHour为相应的 DB 函数:items = items.Where(i =>&nbsp; &nbsp; DbFunctions.AddHour(i.DateCreated, i.DateCreated.Offset.Hours) >= startDate.Value);如果您不使用 SQL Server,那么您需要AddHour在您的数据库中定义函数,定义后您可以使用DbFunctions.AddHour, 来调用它。
打开App,查看更多内容
随时随地看视频慕课网APP