6

我有以下网络服务:

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

我究竟做错了什么?

4

4 回答 4

10

在 DataReader 中选择 r.Name 时,它​​只读取字段名称 - Name。选择字段时,它不包括表说明符(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()
                });
            }
        }
    }
}
于 2012-06-07T21:19:28.230 回答
1

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

尝试类似:

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

然后rdr["RName"]rdr["SName"]将是观众。

于 2012-06-07T21:23:22.757 回答
0

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

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

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

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

if (rdr["RegionName"] != DBNull.Value && rdr["StateName"] != DBNull.Value)
于 2012-06-07T21:21:31.110 回答
0

数据阅读器不知道 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()
                        });
                    }
于 2012-06-07T21:25:20.100 回答