2013-07-11 68 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();