2010-05-04 130 views
1

看看下面的僞C#代碼:在LINQ中打破鏈接Select()是否會損害性能?

using System; 
using System.Data; 
using System.Linq; 
using System.Collections.Generic; 

public IEnumerable<IDataRecord> GetRecords(string sql) 
{ 
    // DB logic goes here 
} 

public IEnumerable<IEmployer> Employers() 
{ 
    string sql = "select EmployerID from employer"; 
    var ids = GetRecords(sql).Select(record => (record["EmployerID"] as int?) ?? 0); 
    return ids.Select(employerID => new Employer(employerID) as IEmployer); 
} 

難道是如果合併這兩個選擇()調用更快?上面的代碼中是否有額外的迭代?下面的代碼更快嗎?

public IEnumerable<IEmployer> Employers() 
{ 
    string sql = "select EmployerID from employer"; 
    return GetRecords(sql).Select(record => new Employer((record["EmployerID"] as int?) ?? 0) as IEmployer); 
} 

我認爲如果性能沒有差異,第一個例子更具可讀性。

+0

這兩個代碼片段是否真的相同?一個有'GetRecords(sql)',另一個'Query.Records(sql)'... – 2010-05-04 05:19:13

+0

@Jeremy - 他們應該是一樣的 - 這是我的錯字 – Justin 2010-05-04 10:14:02

回答

2

沒有顯着性差異。這兩種方法都會返回一個表達式,它可以遍歷GetRecords的結果。

它們並不完全相同,因爲第一個鏈接了Selects,但他們仍然按照相同的順序完成相同的工作。當循環鏈接選擇時,第二個選擇將根據需要從第一個選擇項中放置項目,第一個選擇項不必在第二個選擇項可以使用結果之前完成。

+0

聽起來像是鏈接選擇我有兩個小的狀態機,一個轉移到另一個狀態機。與一體機相比,這不會增加任何顯着的內存開銷? – Justin 2010-05-04 05:49:50

+0

@Justin:是的,他們每個人都有自己的枚舉器(或類似的狀態),所以在處理過程中有一個小的開銷,但這些項目仍然是從GetRecords結果一路處理的,所以沒有積累在記憶中。與從數據庫獲取數據所需的時間相比,額外的開銷可以忽略不計。 – Guffa 2010-05-04 06:06:05

0

沒有區別。

LINQ使用延遲評估的想法source。我將引用相關部分:

爲了解決這個問題,所有內置的LINQ提供程序都使用一種稱爲延遲執行的概念。查詢操作符不是立即執行,而是簡單地返回實現IEnumerable(T)接口的類型。這些類型然後延遲執行,直到查詢被實際用於每個循環的a中。

基本上,直到您使用的Employers()結果在foreach.ToList()等,它實際上並沒有做任何工作。

相關問題