【问题标题】:Getting Error "System.IndexOutOfRangeException". Why?出现错误“System.IndexOutOfRangeException”。为什么?
【发布时间】:2012-06-07 21:18:15
【问题描述】:

我有以下网络服务:

using (SqlCommand cmd = new SqlCommand(@"SELECT r.NAME, s.NAME FROM REGION r LEFT OUTER JOIN STADT s ON s.REGION_ID = r.ID ORDER BY r.NAME", con))
{
    con.Open();
    using (SqlDataReader rdr = cmd.ExecuteReader())
    {
        while (rdr.Read())
        {
            if (rdr["r.NAME"] != DBNull.Value && rdr["s.NAME"] != DBNull.Value)
            {
                stadtObject.Add(new STADT()
                {
                    RegionName = rdr["r.NAME"].ToString(),
                    StadtName = rdr["s.NAME"].ToString()
                });
            }
        }
    }
}

我在SQL Server Management Studio 中测试了 SQL 语句,它的工作原理非常棒。但是,如果我在浏览器中调用该方法,则会出现错误:

System.IndexOutOfRangeException: r.NAME
   at System.Data.ProviderBase.FieldNameLookup.GetOrdinal(String fieldName)
   at System.Data.SqlClient.SqlDataReader.GetOrdinal(String name)
   at System.Data.SqlClient.SqlDataReader.get_Item(String name)
   at StadtHelper.Stadt() in C:\Users\Yeah\Documents\Visual Studio 2010\Projects\WebService1\WebService1\StadtHelper.cs:line 31
   at WebService1.Service1.Stadt() in C:\Depp\Ushi\Documents\Visual Studio 2010\Projects\WebService1\WebService1\Service1.asmx.cs:line 77

我做错了什么?

【问题讨论】:

  • 您是否尝试过调试代码?在rdr["r.name"] 设置断点并查看返回的内容(我不记得这里没有visual studio,但它可能是null 而不是dbnull...)
  • 仅供参考。当 NONE 列匹配时,也会发生此 IndexOutOfRangeException,例如万一有错别字!

标签: c# asp.net sql


【解决方案1】:

当 r.Name 被选中到 DataReader 中时,它只读取 字段 名称 - 名称。选择字段时,不包括表说明符(r. 和 s.)

它找不到“r.Name”或“s.Name”,因为在评估时,阅读器只是返回两列,都刚刚命名为“Name”所以在搜索 r.Name 时,运行时会说“r.Name 不在有效列名列表中”(表现为 IndexOutOfRange 异常)。

如果您希望能够通过名称访问它,则必须使用 AS 语句为查询的不同字段名称提供生成的内存结果:

我认为我说得不好,但从本质上讲,您的代码应该这样修改:

using (SqlCommand cmd = new SqlCommand(@"SELECT r.NAME AS rName, s.NAME AS sName FROM REGION r LEFT OUTER JOIN STADT s ON s.REGION_ID = r.ID ORDER BY r.NAME", con))
{
    con.Open();
    using (SqlDataReader rdr = cmd.ExecuteReader())
    {
        while (rdr.Read())
        {
            if (rdr["rNAME"] != DBNull.Value && rdr["sNAME"] != DBNull.Value)
            {
                stadtObject.Add(new STADT()
                {
                    RegionName = rdr["rNAME"].ToString(),
                    StadtName = rdr["sNAME"].ToString()
                });
            }
        }
    }
}

【讨论】:

  • 非常感谢您的快速帮助! :) 现在它完美了:)
【解决方案2】:

它不喜欢别名 r,这当然会给您带来潜在的问题,因为您的列名不是唯一的。

尝试类似:

Select r.Name as RName, s.Name as SName ...

那么rdr["RName"]rdr["SName"] 将成为观众。

【讨论】:

    【解决方案3】:

    表名不能用于限定SqlDataReader中的字段名;在您的情况下,字段名称是"NAME"

    为避免命名冲突,您应该重命名投影中的列:

    SELECT r.NAME AS RegionName, s.NAME AS StateName FROM REGION r …
    

    然后,使用新名称访问字段:

    if (rdr["RegionName"] != DBNull.Value && rdr["StateName"] != DBNull.Value)
    

    【讨论】:

      【解决方案4】:

      数据读取器不知道 r.NAME 是什么,因为实际返回的列是 NAME 和 NAME。您可以使用别名来区分两者,如下所示:

      SELECT r.NAME as REGION_NAME, s.NAME as STADT_NAME FROM REGION r LEFT OUTER JOIN STADT s ON s.REGION_ID = r.ID ORDER BY r.NAME
      

      然后通过别名访问返回的数据:

      if (rdr["REGION_NAME"] != DBNull.Value && rdr["STADT_NAME"] != DBNull.Value)
                          {
                              stadtObject.Add(new STADT()
                              {
                                  RegionName = rdr["REGION_NAME"].ToString(),
                                  StadtName = rdr["STADT_NAME"].ToString()
                              });
                          }
      

      【讨论】:

        猜你喜欢
        • 2015-10-24
        • 2021-05-22
        • 1970-01-01
        • 2019-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多