LINQ DateTimeOffset表达式无法翻译

3
我有一个Order.cs类,其中包含一个属性:

public string OrderDate { get; set; } = DateTimeOffset.Now.ToString();

我有一个Order dbset。 使用EF,我想获取最近30天的所有订单。 我编写了以下代码:

var now = DateTimeOffset.Now;
 var orders = _context.Orders.Where(o => ((now - DateTimeOffset.Parse(o.OrderDate)).TotalDays < 30)).ToList();

我得到以下错误:
System.InvalidOperationException: The LINQ expression 'DbSet<Order>
.Where(o => (__now_0 - DateTimeOffset.Parse(o.OrderDate)).TotalDays < 30)' 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.

你有什么建议来解决这个问题吗?

编辑

我把OrderDate属性改成了

public DateTime OrderDate { get; set; } = DateTime.Now;

以下是与LINQ查询相关的内容:

var atm = DateTime.Now;
 var orders = _context.Orders.Where(o => (o.OrderDate - atm).TotalDays < 30);

我仍然收到相同的错误信息。


很明显,EF无法将DateTimeOffset.Parse转换为SQL。尽量避免这样的转换。 - undefined
谢谢回复!有什么办法可以绕过这个问题吗? - undefined
回答一下,为什么你要将DateTimeOffset转换成字符串?另外,属性OrderDate没有映射到表格上,因此EF无法为其生成SQL语句。 - undefined
嘿,原因是我之前使用的是SQLite,但现在我切换到了PostgreSQL,订单属性如下所示:public DateTime OrderDate { get; set; } = DateTime.Now; - undefined
1个回答

3
首先,确保了解PostgreSQL中日期和时间处理的工作原理。根据您在数据库中使用的数据类型、在.NET中使用的数据类型以及是否从UTC或本地时间填充它,您将获得不同的结果。
为了减少错误和歧义,我建议使用DateTimeOffset并从UtcNow填充它。我还建议选择更好的属性名称(除非您真的只想存储一个日期)。
public DateTimeOffset OrderTimestamp { get; set; } = DateTimeOffset.UtcNow;

对于这个查询,你应该反转操作。选择截止时间戳并查询在那之后的订单。

var earliestTimestamp = DateTimeOffset.UtcNow.AddDays(-30);
var orders _context.Orders.Where(o => o.OrderTimestamp >= earliestTimestamp);

这样做还有一个性能优点,即查询变得sargable,因此数据库可以使用索引。

非常感谢马特抽出时间详细回答我的问题!你的建议真的让我眼界大开。现在LINQ确实起作用了。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接