如何在DataReader中获取列的序号?

3

如何确定DataReader的结果集中是否存在某列?

我尝试了以下代码:

int columnOrdinal = reader.GetOrdinal("LastName");
columnExists = (columnOrdinal < 0);

但是如果列不存在,GetOrdinal会抛出异常。我的情况并不是异常的情况,相反,它是非常特殊的。
注意:与我的问题无关,但我想知道列是否存在,是因为我想获取列的序数位置,而不会在列不存在时抛出异常:
int columnOrdinal = reader.GetOrdinal("Lastname");

注意:与我的问题无关,但我想知道一个列是否存在的真正原因是我想知道该列是否包含空值:

itIsNull = reader.IsDBNull(reader.GetOrdinal("Lastname"));

不幸的是,IsDBNull 只接受序号,而 GetOrdinal 会抛出异常。所以我只能使用以下代码:

if (ColumnExists(reader, "Lastname"))
{
   itIsNull = reader.IsDBNull(reader.GetOrdinal("Lastname"));
}
else
   itIsNull = false;

注意:虽然与我的问题无关,但我想知道列是否存在的真正原因是有时结果集中不会出现该列,而我不想在处理数据库结果时抛出异常,因为这并不是异常情况。


1
不相关于我的问题异常 - Tomas Voracek
可能是重复的问题:如何在SqlDataReader对象中检查列名 - hatchet - done with SOverflow
@hatchet 那绝对不是我会在数据集的每一行都使用的技术。 - Ian Boyd
@TomasVoracek 我正在尝试避免异常,而你却在抛出更多! - Ian Boyd
如果您阅读上面链接的stackoverflow问题中的其他答案,您会发现GetSchemaTable可能包含实际数据读取器中不存在的列。 - hatchet - done with SOverflow
@hatchet 如果你阅读MSDN,那里有重要信息:“为了确保元数据列返回正确的信息,必须使用KeyInfo设置行为参数调用ExecuteReader。否则,模式表中的某些列可能会返回默认值、空值或不正确的数据。” - Tomas Voracek
1个回答

3
由于IDataReader没有暴露太多有帮助的内容,你能做的有限。使用与类似问题答案中所示的循环

检查SqlDataReader对象中是否存在列名

您可以使用第一行处理时构建一个简单的字典,以列名为键,序数为值(如果您不关心序数值,则使用HashSet)。然后,您只需使用columnDictionary.ContainsKey(“LastName”)作为测试。您只需在遇到第一行时构建字典,然后所有后续行都将快速。

但是,说实话,与数据库时间相比,在其他stackoverflow问题中直接使用解决方案消耗的时间可能是可忽略的。

编辑:这里还有其他可能性:检查数据读取器中是否存在列


问题在于代码针对IDataReader中的每一行只执行一次。每次迭代可能会有四列缺失,而且有40,000次迭代,这意味着会有80,000个异常(而不是零)。答案似乎是“你不能这样做”。我会把“有一个限制...”转化为“不能完成”,并接受它。+1 对于一些解决方法,可能会帮助其他人在其他情况下,但我的问题已经得到了回答。 - Ian Boyd
使用我链接的问题中顶部答案中的方法将避免所有异常。是的,循环会执行很多次,但总成本可能并不高,并且这比陷入异常更加清晰、美观。 - hatchet - done with SOverflow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接