从DataReader读取数据的通用方法

我目前正在使用此方法从DataReader读取数据 –

private T GetValue(object obj) { if (typeof(DBNull) != obj.GetType()) { return (T)obj; } return default(T); } 

将上述方法称为 –

 GetValue(dataReader["columnName1"]) GetValue(dataReader["columnName2"]) GetValue(dataReader["columnName3"]) 

但是,当columnName3的值为7200000且出错时,此操作将失败
Invalid Cast Exception.

我正在考虑修改我的方法来替换 –

 return (T)obj; 

 return (T)Convert.ChangeType(obj, typeof(T)); 

但期待更好的方式,因为这种变化将涉及两次类型铸造。
还有更好的想法?

谢谢!

通用方法的优点是可以减少大量代码膨胀,但是为每种数据类型生成自己的包装器,可以灵活地进行自定义处理。 而且很可能你的数据库查询对性能的影响比检索模式有明显的影响。

我建议你编写一套自己的扩展方法,而不是使用一种通用方法。 在IDataReader上扩展方法可以使您不在整个对象子类型上传播方法。 我不得不单独处理类型,因为各种连接器表现不同,尤其是Guid类型。 当两种情况都返回0时,很难知道datareader是否读取值0DBNull 。 假设表中的枚举字段为空值。 你为什么要把它作为第一个枚举来阅读?

只需致电:

 dataReader.GetInt("columnName1") dataReader.GetString("columnName3") dataReader.GetFloat("columnName3") 

方法:

 public static int? GetInt(this IDataReader r, string columnName) { var i = r[columnName]; if (i.IsNull()) return null; //or your preferred value return (int)i; } public static bool IsNull(this T obj) where T : class { return (object)obj == null || obj == DBNull.Value; } 

同样地,

 public static string GetString(this IDataReader r, string columnName) { } public static float GetFloat(this IDataReader r, string columnName) { } 

如果你真的想要一个通用function,你也可以拥有它。

 public static T Get(this IDataReader r, string columnName, T defaultValue = default(T)) { var obj = r[columnName]; if (obj.IsNull()) return defaultValue; return (T)obj; } 

所以称之为

 dataReader.Get(1); //if DBNull should be treated as 0 dataReader.Get(1); //if DBNull should be treated as null dataReader.Get(1, -1); //if DBNull should be treated as a custom value, say -1 

也就是说,错误是因为你没有像评论中指出的那样使用正确的类型进行转换。 我本可以使用内置的DBNull检查,但我不会避免从读者那里多次读取数据, 这可以从这个奇怪的微优化案例中获得启发

从.NET Framework 4.5开始

 static class SqlReaderExtension { public static async Task ReadAsync(this SqlDataReader reader, string fieldName) { if (reader == null) throw new ArgumentNullException(nameof(reader)); if (string.IsNullOrEmpty(fieldName)) throw new ArgumentException("Value cannot be null or empty.", nameof(fieldName)); int idx = reader.GetOrdinal(fieldName); return await reader.GetFieldValueAsync(idx); } } 

然后

 string result = await reader.ReadAsync("FieldName");