2

假设我正在调用一个查询“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 中的列排序行为?

4

3 回答 3

5

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

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

于 2009-05-28T04:50:19.457 回答
5

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

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

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

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

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

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

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

马克

于 2009-05-28T05:09:45.733 回答
4

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

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);
}
于 2010-07-20T22:33:11.200 回答