通用的方法来读取数据的DataReader [英] Generic method to read data from 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屋!