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

4

我有一个在数据库中运行的查询,我可以看到有一条记录是2013年5月31日的。但是当我从C#使用ADO.NET运行此查询,并使用以下代码时,我会错过2013年5月31日的记录。

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的记录在集合中,那么第一段代码为什么会给出这个结果呢?


你是不是在第二个例子中想要在 While 循环内重新创建 timeSeries 变量?我猜这是一个打字错误吧? - Dave
记录缺失的其他字段有什么值? - kostas ch.
@DaveRook,是的,抱歉那是一个打字错误。 - Christian Phillips
@christiandev,请更新您的帖子,然后我会删除我的评论 :) - Dave
2个回答

8
我认为在第一个例子中你遗漏了一条记录,因为你先将读取器向前移动一位,然后再进行转换。
尝试进行以下更改,看看是否有效:
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();
    }
}

5
有两种迭代数据读取器的方法;一种是不断调用.Read(),另一种是将其视为IDataRecordIEnumerable序列,并使用foreach进行迭代。无论选择哪种方式,都只能迭代一次数据。
  • .Read()的调用从BOF移动到第一条记录,如果有的话。
    • ToList()调用GetEnumerator()然后在循环中调用MoveNext(),这立即向前移动一个位置(因此我们已经丢弃了第一条记录而没有处理它);在ToList()结束时,我们已经遍历完所有数据。
  • 所以外部的.Read()将报告false(EOF)
基本上:这里的问题是使用前进位置的两个API。要么使用.Read(),要么使用foreach API(.ToList())。
附带说明一下,由于列名与成员名匹配,您还可以使用"dapper"来完成大部分工作:
var list = conn.Query<TimeSeries>(sql, args).ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接