泛型方法来读取数据的DataReader(Generic method to read data f

2019-09-22 06:01发布

我目前使用这种方法来读取数据的DataReader -

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

调用上述方法 -

GetValue<int>(dataReader["columnName1"])
GetValue<string>(dataReader["columnName2"])
GetValue<float>(dataReader["columnName3"])

然而,当此操作失败columnName3由具有值7200000 ,错误
Invalid Cast Exception.

我想修改我的方法来替代 -

return (T)obj;

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

但是,期待着一个更好的办法,因为这改变将涉及型铸造两次。
任何更好的想法?

谢谢!

Answer 1:

泛型方法的优点是可以减少大量的代码膨胀,但在其他方面培养出自己的包装为各种数据类型使您可以灵活地定制处理。 而最有可能你的数据库查询会对性能比检索模式产生显着影响。

我建议你写了一套自己的扩展方法比拥有一个通用的办法。 扩展的方法IDataReader给你不传播在整个物品子类方法的好处。 我不得不单独处理类型,因为各种连接器表现不同特别是Guid类型。 也是其很难知道DataReader的读取值0或者DBNull当你返回0 ,对于两种情况。 可以说,没有在你的桌子空值的枚举域。 为什么你想它应该被理解成第一枚举?

只要致电:

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<T>(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)
{
}

如果你真的想要一个通用的功能,你可以拥有它了。

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

    return (T)obj;
}

所以称它为

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

这就是说,这个错误是因为你不正确的类型转换在评论中指出。 我本来可以用内置的DBNull检查,但我不以避免数据从阅读器读取多次, 从microoptimization的这种奇怪的情况下,启发



Answer 2:

使用.NET框架4.5开始

static class SqlReaderExtension
{
    public static async Task<T> ReadAsync<T>(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<T>(idx);
    }
}

接着

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


文章来源: Generic method to read data from DataReader