通用的方法来读取数据的DataReader [英] Generic method to read data from DataReader

查看:155
本文介绍了通用的方法来读取数据的DataReader的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 私人牛逼的GetValue< T>(obj对象)
{
如果(typeof运算(的DBNull)= obj.GetType()!)
{
回报率(T)OBJ;
}
返回默认值(T);
}



调用上面的方法为 -

 的GetValue< INT>(DataReader的[columnName1])
的GetValue<串>(DataReader的[columnName2])
的GetValue<浮动>( DataReader的[columnName3])

但是失败时 columnName3 正与错误结果
无效转换异常。 7200000 p>

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

 收益(T )目标文件; 



 收益率(T)Convert.ChangeType(OBJ的typeof(T)); 



不过,期待着为这一改变更好的办法将涉及类型转换两次。结果
中所述更好的想法?



感谢您!


解决方案

泛型方法的优点是可以减少大量的代码膨胀,但除此之外,搅动了自己的包装为每个数据类型提供您可以灵活地定制处理。而最有可能你的数据库查询会对性能比检索模式有明显的效果。



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



只要致电:

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

和方法:

 公共静态诠释?调用getInt(这IDataReader的R,串COLUMNNAME)
{
变种我= R [COLUMNNAME]
如果(i.IsNull())
返回NULL; //或您的首选价值

回报(INT)I;
}

公共静态布尔ISNULL< T>(这件T OBJ)其中T:类
{
回报(对象)OBJ == NULL || OBJ == DBNull.Value;
}



同样,

 公共静态字符串的GetString(这IDataReader的R,串COLUMNNAME)
{
}

公共静态浮动GetFloat(这IDataReader的R,串COLUMNNAME)
{
}

如果你真的想你了一个通用功能,可以把它太

 公共静态吨得到< T>(这IDataReader的R,串COLUMNNAME,T设置defaultValue =默认(T ))
{
VAR OBJ = R [COLUMNNAME]
如果(obj.IsNull())
返回设置defaultValue;

回报率(T)OBJ;
}



所以称它为

  dataReader.Get< INT>(1); //如果为DBNull应视为0 
dataReader.Get&所述;诠释>(1); //如果为DBNull应被视为无效
dataReader.Get< INT>(1,-1); //如果为DBNull应作为一个自定义的值进行处理,比如-1

这表示,错误的是由于在评论中指出你不正确的类型转换。我本来可以与内置的的DBNull 检查,但我不知道,以避免数据从阅读器,的从microoptimization的这种奇怪的情况下,激发了


I am currently using this method to read data from DataReader -

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

calling above method as -

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

However this fails when columnName3 is having values as 7200000 with error
Invalid Cast Exception.

I am thinking to modify my method to replace -

return (T)obj;

with

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

But looking forward for a better way as this change will involve type casting two times.
Any better ideas?

Thank you!

解决方案

A generic method has the advantage that you can reduce a lot of code bloat, but otherwise churning out your own wrapper for each data type gives you the flexibility to have custom handling. And most probably your db queries will have a noticeable effect on performance than mode of retrieval.

I suggest you to write a set of your own extension methods than having one generic approach. Extending the method on IDataReader gives you the benefit of not propagating the methods on entire object sub types. I have had to individually handle types since various connectors behaved differently especially with Guid type. Also its hard to know if datareader read the value 0 or DBNull when you're returning 0 for both cases. Lets say there is an enum field in your table with a null value. why would you ever want it to be read as the first enum?

Just call:

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

And the methods:

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;
}

And similarly,

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

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

If you really want one generic function you can have it too.

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;
}

So call it

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

That said, the error is because you're not casting with right type as pointed out in comments. I could have gone with built in DBNull checks, but I don't to avoid data being read multiple times from the reader, inspired from this curious case of microoptimization

这篇关于通用的方法来读取数据的DataReader的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆