Ste*_*ven 6 c# entity-framework-core asp.net-core
我有一个非常简单的方法,该方法使用一些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();
}
Run Code Online (Sandbox Code Playgroud)
但是当ToListAsync()被调用时,我得到这个错误:
生成警告“ Microsoft.EntityFrameworkCore.Query.QueryClientEvaluationWarning:LINQ表达式”的错误,其中[[e] .DateCreated.DateTime.AddHours(Convert([e] .DateCreated.Offset.Hours,Double))> = __startDate_Value_0)可以不翻译,将在本地进行评估。”。通过将事件ID'RelationalEventId.QueryClientEvaluationWarning'传递到'DbContext.OnConfiguring'或'AddDbContext'中的'ConfigureWarnings'方法,可以抑制或记录此异常。
问题似乎与AddHours方法有关,如果我将其取出,它就可以正常工作。但是我不知道是否有一种方法可以不使用该方法而使它工作。
我可以在这里使用其他策略吗?
根据此链接,DbFunctionsEF Core 目前不支持。
如果您想AddHour使用 EF Core进行调用,一种选择是AddHour在您的数据库中定义为标量函数,然后您可以在您的 LINQ 查询中调用它。
本文档解释了如何完成:
在 DbContext 上声明一个静态方法并使用以下注释对其进行注释DbFunctionAttribute:
public class MyDbContext : DbContext
{
[DbFunction]
public static int AddHours(DataTime source, int hours)
{
// you don't need any implementation
throw new Exception();
}
}
Run Code Online (Sandbox Code Playgroud)
像这样的方法会自动注册。注册后,对 LINQ 查询中方法的调用可以转换为 SQL 中的函数调用:
items = items.Where(i =>
MyDbContext.AddHours(i.DateCreated, i.DateCreated.Offset.Hours) >= startDate.Value);
Run Code Online (Sandbox Code Playgroud)
免责声明:我个人不喜欢这个解决方案。编写一个新方法,只是为了抛出一个异常,远不是一个优雅的设计。不幸的是,如果您想使用 EF Core,您没有太多选择。
AddHour不是您数据库中的函数。需要翻译成DB中对应的函数。
如果您使用的是 SQL Server,那么您可以使用此代码,它将转换AddHour为相应的 DB 函数:
items = items.Where(i =>
DbFunctions.AddHour(i.DateCreated, i.DateCreated.Offset.Hours) >= startDate.Value);
Run Code Online (Sandbox Code Playgroud)
如果你没有使用 SQL Server,那么你需要AddHour在你的数据库中定义函数,一旦定义你就可以使用DbFunctions.AddHour, 来调用它。
其实翻译DateTime.AddHours方法的支持。
问题是,目前EF核心无法翻译大部分(如果不是全部)的成员DateTimeOffset,在这种特殊情况下-DateTime属性(相同的Offset,DateTimeUtc等等)。
幸运的是,它确实支持DateTimeOffset比较的转换,因此解决方案是另一种方式 - 将DateTime参数转换为DateTimeOffset并在查询中进行简单的比较,例如
if (startDate != null)
{
// Note: must be a variable outside the query expression tree
var startDateOffset = new DateTimeOffset(startDate.Value);
items = items.Where(i => i.DateCreated >= startDateOffset);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
298 次 |
| 最近记录: |