2009-05-28 63 views
1

假设我正在调用一个查询“SELECT name,city,country FROM People”。一旦我执行了我的SqlDataReader,列的排列顺序与我的sql查询中的顺序相同吗?SqlDataReader列常规

换句话说,我可以依靠下面的代码将始终正常工作:

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(); 
} 

也多少表现我输,如果我使用的列名,而不是序数(读者[“名称”])?

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

回答

5

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

至于性能,我认为这可能是非常微不足道的说,开销说,检索下一行数据。

+0

嗨乔希。感谢您的及时答复。那么这种行为是否有保证,我应该依赖它还是使用列名更好? PS - 至于GetOrdinal,我不认为它对我有用,因为我只检索一行。 – niaher 2009-05-28 04:56:26

5

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

但我仍然喜欢使用列名称,因为它更健壮。例如。如果你需要添加一个字段到你的SQL查询怎么办?

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

现在突然间,你不得不重写所有的代码来改变位置....

我通常做的是通过数据读取器返回的所有行列举外循环是什么确定的位置我感兴趣的每个领域:

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

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

马克

4

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

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

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

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); 
}