仅从Entity Framework中的表中检索第一行

时间:2011-12-15 07:30:14

标签: c# sql-server-2008 entity-framework select

背景

使用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

3 个答案:

答案 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