在 c# 中使用 SqlDataReader 填充 List<T>
Posted
技术标签:
【中文标题】在 c# 中使用 SqlDataReader 填充 List<T>【英文标题】:Using SqlDataReader for filling List<T> in c# 【发布时间】:2011-11-11 17:53:33 【问题描述】:我有一个像下面这样的课程,
class Student
public string Name get; set;
public string Surname get; set;
public int Age get; set;
public string Address get; set;
我有一个包含 50,000 条记录的 mysql 表。表结构如下,
ID NAME SURNAME AGE ADDRESS
1 Joe Philip 20 Moscow
2 Misha Johny 25 London
...
我有一个 C# 代码,
List<Student> students = new List<Student>();
string sql = "SELECT name,surname,age,address FROM Students";
command.CommandText = sql;
MySqlDataReader reader = command.ExecuteReader();
while(reader.Read())
Student st = new Student();
st.Name = reader["Name"].ToString();
st.Surname = reader["Surname"].ToString();
st.Age = Convert.ToInt32(reader["Age"].ToString());
st.Address = reader["Address"].ToString();
students.Add(st);
但它的工作速度很慢。您建议使用哪种方法使这段代码运行得更快?
更新:
当我使用这段代码时,
DataTable dt = new DataTable();
adapter.Fill(dt);
效果很好,速度也很正常。但是我用自己的课程尝试有什么问题?
【问题讨论】:
当然很慢。不要一次将 50k 条记录全部读入内存! 这是最快的速度,这里没有明显的改进或疏忽——你需要内存中的所有这些记录吗? 出于好奇,为什么需要将整个数据库表读入内存根本?数据库的一般概念是,它们可能保留比内存容量更多的数据,我们应该逐条处理数据。 看我的回答;如果您告诉我们您将如何处理这些学生数据,您可能会得到更好的答案。 该代码无法编译。您正在将string
分配给 int
属性(年龄)。
【参考方案1】:
如果代码运行缓慢,最大的原因是有50,000条记录。对于 50,000 个Student
对象,您究竟需要什么?如果您能找到一种方法来解决您的问题,而无需读取所有这些记录并创建所有这些对象,那么您将拥有更快的代码。
更新
使用你自己的类很好。大多数情况下,事情运行缓慢是因为您的代码是I/O 绑定(您大部分时间都在等待I/O)。为避免所有这些 I/O,您可以减少检索的数据量(可能通过从数据中删除不相关的列或行)或通过更复杂的查询或存储过程对数据库进行处理。
更新 2
要回答您的后续问题(为什么创建对象列表比获取DataSet
慢),我希望将整个查询读取为DataSet
只会比对象创建稍微快一点。我不熟悉 MySQL .NET 库是如何实现的。令我惊讶的是,这两种方法的速度会有很大的差异。也许MySqlDataReader
正在做一些愚蠢的事情,比如使用内部DataSet
。如果两者之间的性能差异很大,则可能是该库的作者应该修复的问题。
更新 3
MySqlDataAdapter or MySqlDataReader for bulk transfer? 的这个答案有一个很好的提示;设置读者的BatchSize
可能会有所帮助。如果批量大小对于读者来说太小,那么对于像您这样的大量记录来说,它的效率就会降低。
【讨论】:
我编写了考试检查程序。我将使用这个和我没有在这里显示的另一个数据来确定学生的分数。我可以在这里使用 DataSet 而不是 Student 类。但我更喜欢使用我自己的课程。 RAM没有任何问题。仅在用数据填充列表时出现问题。它的工作速度很慢。 在不知道您对数据进行何种处理的细节的情况下,我们无法提供更多帮助。更快的代码是做更少的代码,所以试着找到一种方法让你的代码做更少的事情(例如,将一些处理卸载到数据库中)。查看我的更新。 查看相关问题***.com/questions/2768828/…【参考方案2】:使用记录索引而不是 coulmname 使性能更好一些 使用
st.Name = reader[0].ToString();
instead of
st.Name = reader["Name"].ToString();
and
st.Name = reader[0].ToString();
instead of
st.Name = reader["surname"].ToString();
【讨论】:
还要注意,字符串索引需要适当区分大小写,否则会非常慢。在这种情况下,MySQL ADO.NET 实现很奇怪。而且它仅适用于 MySQL ADO,我测试的所有其他连接器都运行良好。以上是关于在 c# 中使用 SqlDataReader 填充 List<T>的主要内容,如果未能解决你的问题,请参考以下文章
使用 sqldatareader 从另一个线程逐行填充 DataGridView
如何在 JavaScript 中使用 C# SQLDataReader 对象