在迭代之前检测IDataReader是否包含某个字段
时间:2020-03-05 18:50:22 来源:igfitidea点击:
因此,我正在使用IDataReader合并一些业务对象,但是我不知道在运行时确切地知道阅读器中将包含哪些字段。读取器中不存在的任何字段在结果对象上将保留为null。我们如何测试读者是否包含特定字段而不只是将其包装在try / catch中?
解决方案
回答
我们不能仅测试reader [" field"]是否为null或者DBNull,因为如果列不在阅读器中,则会抛出IndexOutOfRangeException。
我在映射层中使用的用于创建域对象的代码以及使用该映射层的存储过程可能具有不同的列名,如下所示;我们可以对其进行修改,以便在未找到该列的情况下不引发异常,并返回default(t)或者null。
我知道这不是最优雅或者最佳的解决方案(实际上,如果可以避免,那么应该这样做),但是,旧式存储过程或者Sql查询可能需要解决方法。
/// <summary> /// Grabs the value from a specific datareader for a list of column names. /// </summary> /// <typeparam name="T">Type of the value.</typeparam> /// <param name="reader">Reader to grab data off of.</param> /// <param name="columnNames">Column names that should be interrogated.</param> /// <returns>Value from the first correct column name or an exception if none of the columns exist.</returns> public static T GetColumnValue<T>(IDataReader reader, params string[] columnNames) { bool foundValue = false; T value = default(T); IndexOutOfRangeException lastException = null; foreach (string columnName in columnNames) { try { int ordinal = reader.GetOrdinal(columnName); value = (T)reader.GetValue(ordinal); foundValue = true; } catch (IndexOutOfRangeException ex) { lastException = ex; } } if (!foundValue) { string message = string.Format("Column(s) {0} could not be not found.", string.Join(", ", columnNames)); throw new IndexOutOfRangeException(message, lastException); } return value; }
回答
尽管我不同意这种方法(我认为在访问数据时应该先了解形状),但我知道也有例外。
我们总是可以使用读取器加载数据表,然后对其进行遍历。然后,我们可以检查该列是否存在。这会降低性能,但是我们不需要try / catch块(因此也许可以满足需求)。
回答
这应该可以解决问题:
Public Shared Function ReaderContainsColumn(ByVal reader As IDataReader, ByVal name As String) As Boolean For i As Integer = 0 To reader.FieldCount - 1 If reader.GetName(i).Equals(name, StringComparison.CurrentCultureIgnoreCase) Then Return True Next Return False End Function
或者(在C#中)
public static bool ReaderContainsColumn(IDataReader reader, string name) { for (int i = 0; i < reader.FieldCount; i++) { if (reader.GetName(i).Equals(name, StringComparison.CurrentCultureIgnoreCase)) return true; } return false; }
:o)
回答
我们也可以使用IDataReader.GetSchemaTable
来获取阅读器中所有列的列表。
http://support.microsoft.com/kb/310107
回答
我使用过的最好的解决方案是这样做的:
DataTable dataTable = new DataTable(); dataTable.Load(reader); foreach (var item in dataTable.Rows) { bool columnExists = item.Table.Columns.Contains("ColumnName"); }
尝试通过reader [" ColumnName"]访问它并检查null或者DBNull将引发异常。