LINQ where子句中的DateTime属性错误

时间:2019-04-21 02:19:45

标签: c# asp.net-core entity-framework-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();
}

但是当调用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方法上,如果我排除的话,它就可以了。但是我不知道是否有一种方法可以不使用该方法而工作。

在这里可以使用其他策略吗?

2 个答案:

答案 0 :(得分:4)

更新后的答案(EF核心):

根据this link,EF Core当前不支持SELECT EMPNO FROM EMP WHERE EMPNO NOT IN (SELECT MGR FROM EMP);

如果要使用EF Core调用import matplotlib.pyplot as plt import numpy as np data_to_plot = [[0.61,0.62,0.6,0.62,0.64,0.63,0.61,0.6,0.57,0.62,0.6,0.62,0.6,0.64,0.61,0.6,0.64,0.58,0.6,0.62], [0.66,0.63,0.63,0.64,0.62,0.67,0.62,0.68,0.58,0.64,0.6,0.64,0.57,0.63,0.59,0.64,0.61,0.58,0.63,0.67], [0.6,0.58,0.59,0.6,0.61,0.57,0.63,0.6,0.57,0.6,0.6,0.6,0.61,0.59,0.59,0.59,0.64,0.59,0.58,0.62], [0.84,0.77,0.83,0.84,0.76,0.74,0.81,0.8,0.83,0.74,0.82,0.8,0.8,0.78,0.81,0.73,0.79,0.8,0.74,0.69]] positions = np.arange(4) + 1 bp = plt.boxplot(data_to_plot, showmeans=True, positions=positions, labels=['ReadUnCommit','ReadCommit','RepeatableRead','Serializable']) means = [np.mean(data) for data in data_to_plot] above_dev = [np.mean(data)+np.std(data) for data in data_to_plot] under_dev = [np.mean(data)-np.std(data) for data in data_to_plot] maxV = [np.max(data) for data in data_to_plot] minV = [np.min(data) for data in data_to_plot] plt.plot(positions, above_dev, 'rs') plt.plot(positions, under_dev, 'bs') plt.plot(positions, maxV, 'ks') plt.plot(positions, minV, 'ys') plt.xlabel("isolation level") plt.ylabel("average execution time") plt.title('S=100,E=20,P=100') plt.show() ,一种选择是在数据库中将DbFunctions定义为标量函数,然后可以在LINQ查询中调用它。

This document解释了如何实现:

在DbContext上声明一个静态方法,并用AddHour对其进行注释:

AddHour

类似的方法会自动注册。注册后,对LINQ查询中的方法的调用可以转换为SQL中的函数调用:

DbFunctionAttribute

原始答案(EF 4/5/6):

public class MyDbContext : DbContext { [DbFunction] public static int AddHours(DataTime source, int hours) { // don't need any implementation throw new Exception(); } } 不是您数据库中的函数。需要将其转换为数据库中的相应功能。

如果您使用的是SQL Server,则可以使用以下代码,它将items = items.Where(i => MyDbContext.AddHours(i.DateCreated, i.DateCreated.Offset.Hours) >= startDate.Value); 转换为相应的DB函数:

AddHour

如果不使用SQL Server,则需要在数据库中定义AddHour函数,一旦定义,就可以使用items = items.Where(i => DbFunctions.AddHour(i.DateCreated, i.DateCreated.Offset.Hours) >= startDate.Value); 来调用它。

答案 1 :(得分:3)

实际上支持DateTime.AddHours方法 的翻译。

问题在于,当前EF Core无法转换DateTimeOffset的大多数(如果不是全部)成员,在这种情况下-DateTime属性(与Offset,{{ 1}}等。

幸运的是,它确实支持翻译DateTimeUtc,因此解决方案是将其转换为其他方法-将DateTimeOffset参数转换为DateTime并执行查询内部的简单比较,例如

DateTimeOffset