使用SqlDataReader从SQL Server取数时首行未加入ArrayList的问题
解决SqlDataReader读取时第一行未加入ArrayList的问题
嘿,这个问题我之前也踩过坑!大概率是你在处理数据的时候,提前调用了一次SqlDataReader.Read()但没处理第一行数据,导致循环直接从第二行开始读取了。
最常见的错误场景
比如你可能写了类似这样的代码:
SqlDataReader reader = komut.ExecuteReader(); // 这里先调用Read()判断是否有数据,但没把第一行加进ArrayList if (reader.Read()) { // 循环里再次调用Read(),此时指针已经跳到第二行 while (reader.Read()) { arrayList.Add(reader["你的列名"]); } }
第一次reader.Read()已经把指针移到了第一行,但你没把这行数据添加到集合里,紧接着循环里的Read()直接跳到第二行,自然就漏掉了第一行。
正确的处理方式
有两种靠谱的写法可以避免这个问题:
1. 直接用while循环(推荐)
reader.Read()本身会返回布尔值,表示是否成功读取到下一行,第一次调用就会读取第一行,完美覆盖所有行:
private void button1_Click(object sender, EventArgs e) { ArrayList arrayList = new ArrayList(); SqlConnection baglanti = new SqlConnection("server=.; Initial Catalog=TripData;Integrated Security=SSPI"); baglanti.Open(); SqlCommand komut = new SqlCommand("select top 50 ...", baglanti); SqlDataReader reader = komut.ExecuteReader(); // 直接用while循环,每次Read()都会读取一行(包括第一行) while (reader.Read()) { // 替换成你实际要读取的列名 arrayList.Add(reader["列名"]); } // 记得关闭资源! reader.Close(); komut.Dispose(); baglanti.Close(); }
2. 用do-while循环(适合需要先判断是否有数据的场景)
如果你必须先确认查询有结果再处理,可以用do-while,先处理第一次Read()的行,再循环读取后续行:
SqlDataReader reader = komut.ExecuteReader(); ArrayList arrayList = new ArrayList(); if (reader.Read()) { do { arrayList.Add(reader["列名"]); } while (reader.Read()); }
额外的优化建议
为了避免资源泄漏,强烈建议用using语句自动管理数据库连接、命令和读取器的资源,不用手动关闭:
private void button1_Click(object sender, EventArgs e) { ArrayList arrayList = new ArrayList(); // using会自动释放资源,即使发生异常也能保证关闭 using (SqlConnection baglanti = new SqlConnection("server=.; Initial Catalog=TripData;Integrated Security=SSPI")) { baglanti.Open(); using (SqlCommand komut = new SqlCommand("select top 50 ...", baglanti)) { using (SqlDataReader reader = komut.ExecuteReader()) { while (reader.Read()) { arrayList.Add(reader["列名"]); } } } } // 这里可以继续处理你的ArrayList }
最后再快速确认下:你的SQL语句在代码里和SQL Server里完全一致吗?有没有可能代码里的查询有拼写错误或者参数问题?不过你说SSMS里执行正常,这个可能性不大,但还是可以快速扫一眼。
内容的提问来源于stack exchange,提问作者Serkan Kaya
相关产品推荐
相关产品推荐

