.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类

Ado.NET SqlDataReader详解

将SqlDataReader的结果映射到对象的最快方法

将 SqlDataReader 的结果映射到对象的最快方法

.NET SqlDataReader对象是否使用数据库游标,或者整个结果集是否已加载到RAM中?

vb.net访问sql server数据库(SqlDataReader和DataSet两种方式)