我有一个非常简单的方法,该方法使用一些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
方法上,如果我排除的话,它就可以了。但是我不知道是否有一种方法可以不使用该方法而工作。
在这里可以使用其他策略吗?
答案 0 :(得分:4)
根据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
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