2012-07-25 21 views
1

我碰到一個同事的代碼,並認爲這是可能的低效.First()是在linq級別還是在返回的可枚舉集合上運行?

bool any = (from c in listDeviceMaxDate 
      where c.DeviceKey == m_deviceList[i].deviceKey 
      select c).Any(); 

if (!any) 
{ 
    latestDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue; 
} 
else 
{ 
    // from the list we have get the lastest max date from the flow table 
    DeviceDateTimeItem temp = (from c in listDeviceMaxDate 
           where c.DeviceKey == m_deviceList[i].deviceKey 
           select c).First(); 

    latestDate = Convert.ToDateTime(temp.dateTimeMax); 
} 

我的第一直覺是存儲LINQ查詢,然後就引用它作爲必要的,但後來我意識到,First()運營商可以防止LINQ從實際獲取無約束查詢將執行的所有行。

如何最初想過重組代碼:

var deviceList = from c in listDeviceMaxDate 
          where c.DeviceKey == m_deviceList[i].deviceKey 
          select c; 

if (!deviceList.Any()) 
{ 
    latestDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue; 
} 
else 
{ 
    // from the list we have get the lastest max date from the flow table 
    DeviceDateTimeItem temp = deviceList.First(); 

    latestDate = Convert.ToDateTime(temp.dateTimeMax); 
} 

我的問題是做第二LINQ查詢First()呼叫阻止其返回的所有結果,因此,它實際上是更快地做到這一點原來的方式?

+1

這是LINQ to SQL的? '在'IEnumerable '上運行的First()'是Linq。 'System.Data.Linq'上的'IQueryable '的First()'是Linq to SQL。 – 2012-07-25 11:16:14

回答

3

它實際上取決於它是什麼LINQ實現。如果它是LINQ到對象(即IEnumerable<T>),那麼它是基本上只是列舉數據無論它是,並返回第一個項目,如果一個。所以First()是道德等價的:

foreach(var val in sequence) return val; 
throw OopsNoData(); 

Any()應該很好地比較:

foreach(var val in sequence) return true; 
return false; 

(它可能使用在實際執行原始迭代器,而不是foreach

然而!如果它是LINQ-to-anything-else,則所有投注都關閉。 LINQ查詢(特別是IQueryable<T>)被設計爲可組合的 - 例如,我期望LINQ-to-SQL將First()變成select TOP 1 ... TSQL查詢,對於大多數其他數據庫後端也如此。所以是的,告訴它你只想要一行應該是有幫助的。然而!我也希望.Any()做一些非常相似的事情,所以不應該(理論上)是一個很大的區別。在完美的世界中,它甚至可能在TSQL中使用exists(...),但這個世界遠非完美。

找出方法:附上一個SQL跟蹤器,並查看最終的TSQL是什麼。


最終的方式做,這是簡單的:

var obj = someQuery.FirstOrDefault(); 
if(obj == null) { 
    // no match 
} else { 
    // do something with "obj" 
} 
相關問題