SqlDataReader因未知原因关闭

3

我是一名 C# 初学者。我正在尝试使用以下代码从 SQL 数据库获取一些数据,但是出现了错误:System.InvalidOperationException: 'Invalid attempt to call Read when reader is closed.'

在网上搜索答案后,我什么也没找到,也许有人能看出问题在哪里?

错误发生在:while (rdr.Read())

谢谢!

internal List<string> GetInflationByYearData(string Country, int StartYear, 
int EndYear)
        {
            string CS = 
ConfigurationManager.ConnectionStrings["Connection"].ConnectionString;
            using (SqlConnection con = new SqlConnection(CS))
            {
                SqlCommand cmd = new SqlCommand("SpCountryData", con)
                {
                    CommandType = System.Data.CommandType.StoredProcedure
                };
                cmd.Parameters.AddWithValue("@act", 
"getInflationByYearData");
                cmd.Parameters.AddWithValue("@Country", Country);
                cmd.Parameters.AddWithValue("@startYear", StartYear);
                cmd.Parameters.AddWithValue("@endYear", EndYear);
                var table = new DataTable();
                con.Open();
                SqlDataReader rdr = cmd.ExecuteReader();
                while (rdr.Read())
                {
                    {
                        table.Load(rdr);
                    };
                }
                //con.Close();
                List<string> labelList = new List<string>();
                List<string> valueList = new List<string>();
                if (table.Rows.Count > 0)
                {
                    foreach (DataRow row in table.Rows)
                    {
                        string label = row["Year"].ToString();
                        string value = row["Percentage"].ToString();
                        labelList.Add(label);
                        valueList.Add(value);
                    }
                }
                List<string> list = new List<string>();
                StringBuilder sbLabels = new StringBuilder();
                foreach (string lbl in labelList)
                {
                    sbLabels.Append(lbl + ",");
                }
                StringBuilder sbValues = new StringBuilder();
                foreach (string val in valueList)
                {
                    sbValues.Append(val + ",");
                }
                list.Add(sbLabels.ToString().Substring(0, sbLabels.Length - 
1));
                list.Add(sbValues.ToString().Substring(0, sbValues.Length - 
1));
                return list;
            }
        }
2个回答

5
Load方法会消耗reader中的数据直到读取结束;你应该选择使用while (rdr.Read())循环或者调用table.Load(rdr),而不是两者都使用。实际上,Load方法在内部执行了相同的循环操作。
因此:移除循环 - 直接使用Load方法即可。
然而!如果你只需要将数据作为List<string>类型获取,那么将其加载到DataTable中似乎是一个不必要的步骤(DataTable并不轻量级)- 似乎可以在reader中完成这一步骤,或者使用其他工具(如“dapper”)来实现。
不清楚YearPercentage是什么数据类型,但以下是一个“dapper”的示例...
class MyRowThing {
    public int Year {get;set;}
    public decimal Percentage {get;set;}
}

var rawData = con.Query<MyRowThing>("SpCountryData",
    new { // params here
        act = "getInflationByYearData", Country,
       startYear = StartYear, endYear = EndYear
    }, commandType: CommandType.StoredProcedure).AsList();

// now loop over rawData, which is a List<MyRowThing> with the data

谢谢,我移除了循环后它可以工作了。我对“Load”这个东西一无所知。这个函数应该返回一个包含两个字符串的列表,用于生成 Chart.js 图表的数据集和标签。这是我第一次听说 Dapper。它看起来更短、更简单。再次感谢你,Marc! :) - Cristi Priciu
1
@dapper 是我们在 Stack Overflow 使用(并编写)的工具 - 它旨在非常易于使用和明显(不像原始的 ADO.NET),并且在执行时非常快速和高效 :) - 可在 NuGet 上获得:https://www.nuget.org/packages/Dapper/ - Marc Gravell

2

替换:

  var table = new DataTable();
                con.Open();
                SqlDataReader rdr = cmd.ExecuteReader();
                while (rdr.Read())
                {
                    {
                        table.Load(rdr);
                    };
                }
                //con.Close();
                List<string> labelList = new List<string>();
                List<string> valueList = new List<string>();
                if (table.Rows.Count > 0)
                {
                    foreach (DataRow row in table.Rows)
                    {
                        string label = row["Year"].ToString();
                        string value = row["Percentage"].ToString();
                        labelList.Add(label);
                        valueList.Add(value);
                    }
                }

使用:

    con.Open();

    List<string> labelList = new List<string>();
    List<string> valueList = new List<string>();
    SqlDataReader rdr = cmd.ExecuteReader();
    while (rdr.Read())
    {
            labelList.Add(rdr["Year"].ToString());
            valueList.Add(rdr["Percentage"].ToString());
    }

将更换DataTable以获得更优化的代码。


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