C# 出现错误“System.IndexOutOfRangeException”。为什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10940037/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting Error "System.IndexOutOfRangeException". Why?
提问by Bashud
I have the following Webservice:
我有以下网络服务:
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()
});
}
}
}
}
I tested the SQL Statement in SQL Management Studio and ist working like a charm. But I am getting an Error if i invoke the Method in the Browser :
我在 SQL 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
I don't know what I am doing wrong. Maybe you can help me.
我不知道我做错了什么。也许你可以帮助我。
Thank you in advance.
先感谢您。
采纳答案by David
When r.Name is selected into the DataReader, it reads only the fieldname - Name. When selecting the fields, it doesn't include the table specifiers (r. and s.)
当 r.Name 被选入 DataReader 时,它只读取字段名称 - Name。选择字段时,不包括表说明符(r. 和 s.)
It can't find "r.Name" or "s.Name" because when evaluating, the reader is simply returning two columns, both just named "Name" So whe searching for r.Name, the runtime is sayinf that "r.Name is not in the list of valid column names" (which is manifested in an IndexOutOfRange exception).
它找不到“r.Name”或“s.Name”,因为在评估时,读取器只是返回两列,都只是命名为“Name”所以当搜索 r.Name 时,运行时会说“r.Name”。名称不在有效列名列表中”(这体现在 IndexOutOfRange 异常中)。
If you want to be able to access it by name, you have to use the AS statement to give the resulting in-memory results of the query distinct field names:
如果您希望能够通过名称访问它,您必须使用 AS 语句来给出查询不同字段名称的结果内存结果:
I think I'm stating that badly, but in essence, your code should be modified as such:
我想我说得不好,但本质上,你的代码应该这样修改:
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()
});
}
}
}
}
回答by Douglas
Table names cannot be used to qualify the field names in a SqlDataReader; the field name, in your case, is "NAME".
表名不能用于限定 a 中的字段名SqlDataReader;在您的情况下,字段名称是"NAME".
To avoid the naming conflict, you should rename the columns in your projection:
为避免命名冲突,您应该重命名投影中的列:
SELECT r.NAME AS RegionName, s.NAME AS StateName FROM REGION r …
Then, access the fields using the new names:
然后,使用新名称访问字段:
if (rdr["RegionName"] != DBNull.Value && rdr["StateName"] != DBNull.Value)
回答by Tony Hopkinson
Doesn't like the alias r, which of cource gives you a potential problem as your column names are not unique.
不喜欢别名 r,这当然会给您带来潜在问题,因为您的列名不是唯一的。
try something like
尝试类似
Select r.Name as RName, s.Name as SName...
Select r.Name as RName, s.Name as SName...
then rdr["RName"]and rdr["SName"]will be goers.
然后rdr["RName"],rdr["SName"]将是观众。
回答by Lucian
The data reader doesn't know who r.NAME is because the columns that are actually returned are NAME and NAME. You can use aliases to differentiate the two, like this:
数据读取器不知道 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
and then access the returned data by the alias:
然后通过别名访问返回的数据:
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()
});
}

