在 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>的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中使用 SqlDataReader 获取行数

使用 sqldatareader 从另一个线程逐行填充 DataGridView

如何在 JavaScript 中使用 C# SQLDataReader 对象

在 C# 中将 SQL Datareader 转换为数据集

如何使用 SqlDataReader 像使用 SqlDataAdapter 一样快地填充 DataTable?

C# 在 SqlDataReader 中禁用自动格式化