.NET SqlDataReader Item[] 与 GetString(GetOrdinal())?
Posted
技术标签:
【中文标题】.NET SqlDataReader Item[] 与 GetString(GetOrdinal())?【英文标题】:.NET SqlDataReader Item[] vs. GetString(GetOrdinal())? 【发布时间】:2011-05-16 16:05:48 【问题描述】:使用SqlDataReader
类,如果有的话,它们之间的功能差异是什么:
(string) dataReader["MyFieldName"];
和
dataReader.GetString(dataReader.GetOrdinal("MyFieldName"));
【问题讨论】:
DataReader ordinal-based lookups vs named lookups 的可能重复项 【参考方案1】:抛开选角问题不谈,对于单数调用,没有。索引器将调用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());
【讨论】:
【参考方案2】:处理空值时:
// 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"));
【讨论】:
我回滚了最后一次编辑,因为 OP 的问题是询问两个语句之间的功能差异 - 这个答案突出了处理空值时的差异,编辑显示了如何检查空值,不要'不知道这与 OP 的问题有什么关系。【参考方案3】:在第一种情况下,您正在强制转换,特别是对于值类型(涉及拆箱)。就我个人而言,我总是使用第二个,这是我向您推荐的。
【讨论】:
好的,在第一种情况下,肯定涉及最后一分钟的拆箱。但是你确定在第二种情况下,在这个过程中的任何地方都没有类似的东西吗?【参考方案4】://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"));
Serendipity 是一种奇妙的发现方法。
【讨论】:
这里的元评论是怎么回事?你想回答这个问题吗?【参考方案5】:作为 casperOne 答案的替代方案,可以很容易地减少在应用程序生命周期中发生一次序数查找。也可以不用手动维护变量来记录每个索引。
以下代码要求每个类有一个查询,如果您想在一个类中处理多个查询,这很容易实现。
从一个字段开始:
static readonly ConcurrentDictionary<string, int> OrdinalMap =
new ConcurrentDictionary<string, int>();
然后更新您的访问代码,类似于:
reader.GetString(OrdinalMap.GetOrAdd("MyFieldName", reader.GetOrdinal))
现在您可以使用线程安全的 O(1) 查找序数,而无需维护任何手动映射的变量或 const 用法,如果您更改查询会破坏世界。这并不重要,但只是为了清楚起见,如果您同时执行许多查询,则由于 GetOrAdd 的行为,reader.GetOrdinal("MyFieldName")
可能会被执行多次,而不是完全一次,而是出于所有意图和目的可以被视为一次。
【讨论】:
以上是关于.NET SqlDataReader Item[] 与 GetString(GetOrdinal())?的主要内容,如果未能解决你的问题,请参考以下文章
ADO.NET_SqlConnection类,SqlCommand类,SqlDataReader类