我正在使用IDataReader来填充一些业务对象,但是在运行时我不知道读取器中确切的字段是什么。任何不在读取器中的字段都将在生成的对象上保留为空值。如何测试读取器是否包含特定字段而不仅仅是用try/catch语句封装它?
我正在使用IDataReader来填充一些业务对象,但是在运行时我不知道读取器中确切的字段是什么。任何不在读取器中的字段都将在生成的对象上保留为空值。如何测试读取器是否包含特定字段而不仅仅是用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
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)
Enumerable.Range(0, reader.FieldCount).Any(i => reader.GetName(i) == "ColumnName")
DataTable dataTable = new DataTable();
dataTable.Load(reader);
foreach (var item in dataTable.Rows)
{
bool columnExists = item.Table.Columns.Contains("ColumnName");
}
尝试通过 reader["ColumnName"] 访问它并检查是否为 null 或 DBNull 会抛出异常。
你不能仅仅测试reader["field"]是否为null或DBNull,因为如果列不在reader中,则会抛出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;
}
reader.GetSchemaTable().Rows.Cast<DataRow>().Select(x => (string)x["ColumnName"]).Contains(colName, StringComparer.OrdinalIgnoreCase)
与Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).Contains(colName, StringComparer.OrdinalIgnoreCase)
进行对比。FieldCount方法不仅更简洁,而且速度快得多。 - nawfal