将Ado.net DataReader转换为IDataRecord会产生奇怪的结果

我有一个针对数据库运行的查询,我可以看到有一个31/05/2013的记录。 当我使用ADO.NET从C#运行此查询,然后使用以下代码时,我错过了31/05/2013的记录

var timeSeriesList = new List(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { timeSeriesList = reader.Cast() .Select(r => new TimeSeries { MidRate = (double)r["MidRate"], RiskFactorName = (string)r["RiskFactorName"], SeriesDate = (DateTime)r["SeriesDate"] }).ToList(); } } 

但是,如果我对此代码使用相同的查询:

 var timeSeriesList = new List(); using (var reader = cmd.ExecuteReader()) { while (reader.Read()) { var timeSeries = new TimeSeries { MidRate = (double)reader["MidRate"], RiskFactorName = (string)reader["RiskFactorName"], SeriesDate = (DateTime)reader["SeriesDate"] }; timeSeriesList.Add(timeSeries); } } 

…然后2013年5月31日的记录在集合中 – 为什么第一个代码块会给出这个结果?

我认为你在第一个例子中缺少记录,因为你将读者移动一个然后再将其转换。

尝试此更改,看看它是否有效:

 var timeSeries = new List(); using (var reader = cmd.ExecuteReader()) { if (reader.HasRows) { timeSeries = reader.Cast() .Select(r => new TimeSeries { MidRate = (double)r["MidRate"], RiskFactorName = (string)r["RiskFactorName"], SeriesDate = (DateTime)r["SeriesDate"] }).ToList(); } } 

有两种方法可以通过数据读取器进行迭代; 一个是继续打电话.Read() ; 另一种方法是将它作为IDataRecordIEnumerable序列处理并foreach它; 无论您选择哪种,您只能迭代一次数据。

  • .Read()的调用从BOF移动到第一个记录(如果有的话)
    • ToList()在一个循环中调用GetEnumerator()然后MoveNext() ,该循环立即向前移动一个位置 (所以我们将第一个记录放在地板上而不处理它); 在ToList()的末尾,我们已经咀嚼了所有数据
  • 所以外部.Read()将报告false (EOF)

基本上:这里的问题是使用两个API来推进这个位置。 使用.Read() ,或使用foreach API( .ToList() )。

作为旁注,由于列名称与成员名称匹配,您还可以使用“dapper”来完成繁重的工作:

 var list = conn.Query(sql, args).ToList();