2013-07-11 66 views
1

考慮下面的代碼剪斷:枚舉SqlDataReader的列

using (var reader = cmd.ExecuteReader()) 
{ 
    while(reader.Read()) 
    { 
     var count = reader.FieldCount; // the first column must be name all subsequent columns are treated as data 
     var data = new List<double>(); 
     for (var i = 1; i < count; i++) 
     { 
      data.Add(Convert.ToDouble(reader[i].ToString())); 
     } 
     barChartSeries.Add(new ColumnBarChart.ColumnChartSeries((string)reader[0], 
                   data)); 
     columnChart.xAxis.categories.Add((string)reader[0]); 
    } 
} 

有沒有一種簡單的方法來消除for循環?也許使用linq?

閱讀[0]永遠是一個字符串 讀者[0+?]將是一個雙

我想如果可能的話所有的雙打拉成一個列表。

+3

你爲什麼要*消除這裏的循環?我會擺脫雙倍字符串到雙倍的轉換(使用'GetDouble'來代替),但剩下的對我來說似乎還可以... –

+0

@JonSkeet好點 - 我不喜歡循環。這將拉取一個存儲爲json的HighChart對象,反序列化對象,然後根據對象中的conStr標識符查詢數據庫(可能是一個不同的數據庫),然後解析數據,然後重新序列化爲json以在REST中返回服務。速度是我想的某個問題。 – Wjdavis5

+0

你可以用'Enumerable.Range'替換'for'並用'Linq'來完成,但基本上你只是用'foreach'替換'for',在這種情況下,你的代碼對我來說似乎很好,我可以看到沒有重構'for'循環的好處 –

回答

7

速度是有點擔心,我想的。

然後你專注於完全錯誤的問題。

你在這裏做的事情,循環是至少低效的部分。更令人擔憂的是,您將從double轉換爲string,然後回到double。至少修復您的代碼:

for (var i = 1; i < count; i++) 
{ 
    data.Add(reader.GetDouble(i)); 
} 

你可以用已知的尺寸創建列表,太:

List<double> data = new List<double>(count - 1); 

即使是這樣,我強烈懷疑這回事與序列化和數據庫進行比較是不相關的訪問。

無論你做什麼,東西將循環。你可以盡全力去循環(例如通過編寫一個擴展方法遍歷一行中的所有值) - 但是真的,我沒有看到它在這裏有什麼問題。

我強烈建議您避免微觀優化,直到證明出現問題。如果你擔心的這部分代碼完全是瓶頸,我會非常驚訝。一般來說,你應該寫出最簡單的代碼,以達到你想要的目標,決定你的性能標準,然後對它們進行測試。只在需要時才離開簡單的代碼。

+1

謝謝。我明白你在說什麼。我欣賞智慧的話語。 – Wjdavis5

0

我不認爲你可以循環就可以了,因爲

public class SqlDataReader : DbDataReader, IDataReader, IDisposable, IDataRecord 

這個類沒有實現IEnumerable

+2

'SqlDataReader'擴展了'DbDataReader',它實現了'IEnumerable'。它只是不執行'IEnumerable ',但你可以使用'Cast '對它 – TheEvilPenguin

+1

我沒有任何東西,當jon雙向回答你的問題;) –

1

我可以看到刪除forloop是使用Enumerable.Range的唯一途徑。

但無論如何,你可以這樣做:

var data = new List<double>(Enumerable.Range(1, count).Select(i => reader.GetDouble(i))); 

但我看不出有什麼好處這種計算策略,它只是使代碼不可讀

0

您可以使用LINQ Cast方法獲得可以使用其他LINQ方法的東西,但我同意其他的海報 - for循環沒有任何問題。 LINQ方法只會在後臺使用效率較低的循環。

我相信這應該可以工作,但還沒有建立一個數據集來測試它。

reader.Cast<Double>().Skip(1).ToList();