背景
使用SQL Server 2008的实体框架4
问题:
我有一张桌子Order
。每行都有一列Timestamp
。
用户可以选择过去的一些时间,我需要让Order
最接近指定的时间,但这是在指定的时间之前发生的。换句话说,在指定时间之前的最后一个订单。
例如,如果我有订单
2008-01-12
2009-04-17
2009-09-24
2010-11-02
2010-12-01
2011-05-16
并选择日期2010-07-22
,我应该获得2009-09-24 order
,因为这是指定日期之前的最后一个订单。
var query = (from oData in db.OrderDatas
where oData.Timestamp <= userTime
orderby oData.Timestamp ascending
select oData).Last();
这与我的尝试最接近。但是,我不确定Last运算符在转换为SQL时是如何工作的,如果它完全被翻译的话。
问题:
此查询是否会获取所有数据(早于userTime
)然后获取最后一个元素,还是将其翻译以便只从数据库返回一个元素?我的表可以容纳非常多的行(100000+),因此性能是一个问题。
另外,如何检索数据库中最接近的时间(不一定是更早的时间)?在2010-07-22
的示例中,可以得到2010-11-02
,因为它更接近指定的日期而不是2009-09-24
。
答案 0 :(得分:13)
通常,如果您担心LINQ的行为方式,您应该检查SQL发生的做什么。如果您还没有弄清楚如何查看LINQ查询如何转换为SQL,那么这应该是您接下来要做的事情。
正如您在评论中所指出的那样Last()
isn't supported by LINQ to SQL所以对EF来说也是如此。幸运的是,使用First()
代码很容易:
var query = (from oData in db.OrderDatas
where oData.Timestamp <= userTime
orderby oData.Timestamp descending
select oData).First();
答案 1 :(得分:1)
问题:
此查询是否会获取所有数据(早于userTime)然后获取 最后一个元素,或者它将被翻译为只有一个元素 将从数据库返回?我的桌子可以容纳很大 行数(100000+)因此性能是一个问题。
在这种情况下,使用first()方法,查询将立即执行,并将以这样的方式进行优化,即它将检索1条记录。最有可能是顶级(1)选择。您确实需要使用sql profilihg工具或使用datacontext的日志来检查生成的sql。或者你可以使用linqpad。如果没有使用正确的方法,linq-2-sql可以导致N + 1个查询。这种行为是可以预测的,但最初你必须要注意。
答案 2 :(得分:1)
尝试使用:
var query = (from oData in db.OrderDatas
where oData.Timestamp <= userTime
orderby oData.Timestamp descending
select oData).Take(1);
相当于TOP 1