使用SqlDataReader
类时,以下两种方式在功能上有什么区别(如果有的话):
(string) dataReader["MyFieldName"];
并且
dataReader.GetString(dataReader.GetOrdinal("MyFieldName"));
使用SqlDataReader
类时,以下两种方式在功能上有什么区别(如果有的话):
(string) dataReader["MyFieldName"];
并且
dataReader.GetString(dataReader.GetOrdinal("MyFieldName"));
除了类型转换问题之外,在单次调用中是没有其他问题的。索引器将调用DbDataReader.GetOrdinal
,然后调用适当的Get
方法以获取值(请注意,使用序数调用Get
方法比使用字段名称的索引器更快)。
然而,这将每次都需要进行序数查找。如果你正在以只向前、只读的方式迭代一些记录(这正是DbDataReader
实例的意图),那么可以通过仅在一次查找时进行来减少此查找的开销。
可以像这样做:
// Move to the first record. If no records, get out.
if (!dataReader.Read()) return;
// Before the loop. Can do this for any other fields being
// accessed in the loop as well.
int myFieldNameOrdinal = dataReader.GetOrdinal("MyFieldName");
// Process the records. Remember, already on the first record, so
// use do/while here.
do
{
// Do something with your field.
Console.WriteLine(dataReader.GetString(myFieldNameOrdinal));
} while (dataReader.Read());
在处理空值时:
// Will throw an InvalidCastException
// Exception Message will be "Unable to cast object of type System.DBNull
// to System.String
(string) dataReader["MyFieldName"];
// Will throw a SqlNullValueException
// Exception Message will be "Data is Null. This method or property
// cannot be called on Null values."
dataReader.GetString(dataReader.GetOrdinal("MyFieldName"));
在第一种情况下,你需要强制类型转换,这对于值类型来说很不好看(会涉及到拆箱)。个人而言,我总是使用第二种方法,并且我建议你也这样做。
//Well, we want to avoid the null exception issue entirely.
//Let's check for null first, before we try to use the value.
if( !dataReader.IsDBNull(dataReader.GetOrdinal("MyFieldName")))
{
//Store my data or use the value
string mystring=dataReader.GetString(dataReader.GetOrdinal("MyFieldName"));
}
偶然发现法是一种很棒的发现方法。
static readonly ConcurrentDictionary<string, int> OrdinalMap =
new ConcurrentDictionary<string, int>();
然后更新您的访问代码,类似于:
reader.GetString(OrdinalMap.GetOrAdd("MyFieldName", reader.GetOrdinal))