【问题标题】:SqlDataReader Column OrdinalsSqlDataReader 列序号
【发布时间】:2010-10-29 11:40:09
【问题描述】:

假设我正在调用一个查询“SELECT name, city, country FROM People”。执行 SqlDataReader 后,列的顺序是否与我的 sql 查询中的顺序相同?

换句话说,我可以相信以下代码将始终正常工作:

SqlConnection connection = new SqlConnection(MyConnectionString);
SqlCommand command = new SqlCommand();
command.Connection = connection;
command.CommandText = "SELECT [name], [city], [country] WHERE [id] = @id";

try
{
    connection.Open();
    SqlDataReader reader = command.ExecuteReader(System.Data.CommandBehavior.SingleRow);

    if (reader.Read())
    {
        // Read values.
        name = reader[0].ToString();
        city = reader[1].ToString();
        country = reader[2].ToString();
    }
}
catch (Exception)
{
    throw;
}
finally
{
    connection.Close();
}

另外,如果我使用列名而不是序数 (reader["name"]),我会损失多少性能?

是否有任何官方的微软文档描述了SqlDataReader 中的列排序行为?

【问题讨论】:

    标签: asp.net sql sql-server ado.net sqldatareader


    【解决方案1】:

    是的,但您也可以使用 SqlDataReader.GetName(ordinal) 和 SqlDataReader.GetOrdinal(name)。

    至于性能,我认为与检索下一行数据的开销相比,它可能非常微不足道。

    【讨论】:

    • 嗨乔希。感谢您的及时答复。那么这种行为是否得到保证,我应该依赖它,还是最好使用列名? PS - 至于 GetOrdinal,我认为它在我的情况下没有用,因为我只检索一行。
    • 是的,这种行为是有保证的,尽管除了使用 SqlDataReader 的几年之外,我没有任何核心证据来支持它。我通常使用列名,除非只有 1 或 2 列,因为它更难阅读。
    • 但实际上我从不使用 reader[0]、reader[1] 等。我会使用 reader.GetString(0)、reader.GetString(1) 等...
    • @Josh:我碰巧记得这种行为记录在 MSDN 上......但我现在懒得去寻找链接。 ;-)
    【解决方案2】:

    我完全同意 Josh - 字段的位置确实如您在 SQL 查询文本中指定的那样。

    但是:我仍然更喜欢使用列名,因为它更健壮。例如。如果您需要在 SQL 查询中添加字段怎么办?

    command.CommandText = "SELECT [name], [jobtitle], [city], [country] WHERE [id] = @id";
    

    现在突然你必须重写所有代码来改变位置......

    我通常在枚举数据读取器返回的所有行的循环之外做的是确定我感兴趣的每个字段的位置:

    int namePosition = reader.GetOrdinal("name");
    int cityPosition = reader.GetOrdinal("city");
    

    然后我在处理数据的循环中使用这些位置来快速访问各个字段。这样你只确定一次位置,但你在循环数据中使用位置 - 两全其美! :-)

    马克

    【讨论】:

      【解决方案3】:

      这个例子是最易维护和最容易阅读的:

      int? quantity = reader.Get<int?>("Quantity");
      Guid token = reader.Get<Guid>("Token");
      

      它依赖于我创建的以下扩展方法。它执行 DB 空值检查,在未找到字段时提供信息性错误消息,并且在重新对齐列时不会中断。

      internal static T Get<T>(this SqlDataReader reader, string fieldName)
      {
          int ordinal;
          try
          {
              ordinal = reader.GetOrdinal(fieldName);
          }
          catch (IndexOutOfRangeException)
          {
              throw new IndexOutOfRangeException(string.Format("Field name '{0}' not found.", fieldName));
          }
      
          return !reader.IsDBNull(ordinal) ? (T)reader.GetValue(ordinal) : default(T);
      }
      

      【讨论】:

        猜你喜欢
        • 2015-04-04
        • 2013-04-07
        • 2013-02-09
        • 1970-01-01
        • 1970-01-01
        • 2010-10-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多