将Ado.net DataReader转换为IDataRecord给出奇怪的结果

本文关键字:结果 IDataRecord net Ado DataReader 转换 | 更新日期: 2023-09-27 18:16:55

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

var timeSeriesList = new List<TimeSeries>();  
using (var reader = cmd.ExecuteReader())
{
    while (reader.Read())
    {
        timeSeriesList = reader.Cast<IDataRecord>()
            .Select(r => new TimeSeries
                 {
                     MidRate = (double)r["MidRate"],
                     RiskFactorName = (string)r["RiskFactorName"],
                     SeriesDate = (DateTime)r["SeriesDate"]
                 }).ToList();
    }
}
但是,如果我使用相同的查询代码:
var timeSeriesList = new List<TimeSeries>();                        
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);
    }
}

…那么31/05/2013的记录就在集合中——为什么第一个代码块会给出这个结果?

将Ado.net DataReader转换为IDataRecord给出奇怪的结果

我认为你在第一个例子中缺少记录,因为你将reader移动了一个,然后将其强制转换。

尝试这个更改,看看是否有效:

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

有两种遍历数据阅读器的方法;一个是一直叫.Read();二是将其视为IDataRecordforeachIEnumerable序列;无论您选择哪一种,您都只能迭代数据一次。

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

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

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

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