将Generic类与SqlDataReader GetValue一起使用

时间:2014-11-19 17:09:38

标签: c# generics sqldatareader

我的代码适用于没有NULL值的数据库

public T GetField<T>(SqlDataReader dr, string fieldName)
{
    return (T)dr.GetValue(dr.GetOrdinal(fieldName));
}

然后我想控制DBNull值,因为它们已经存在于某些表中,我升级了这个函数:

public T GetField<T>(SqlDataReader dr, string fieldName) where T : new()
{
    var value = dr.GetValue(dr.GetOrdinal(fieldName));   
    return value is DBNull ? new T() : (T)value;
}

但是现在,我不能要求GetField<string>,因为string没有带0参数的构造函数。

我试图创建另一个像Abstract一样的函数,没有任何限制,只有像这样的字符串类型

public string GetField<string>(SqlDataReader dr, string fieldName)
{
    var value = dr.GetValue(dr.GetOrdinal(fieldName));   
    return value is DBNull ? "" : value.ToString();
}

但答案是它们的定义不明确,因为即使应用了限制,T也包含字符串。

我可以为每种数据类型创建独立的函数,但我更喜欢抽象的解决方案,因为它更清晰。

我错过了什么吗?

谢谢!

2 个答案:

答案 0 :(得分:5)

您的最终方法会失败,因为它尝试声明名为string的类型参数。

我建议您添加另一个没有T约束的重载,但使用默认值:

public T GetField<T>(SqlDataReader dr, string fieldName, T defaultValue)
{
    var value = dr.GetValue(dr.GetOrdinal(fieldName));   
    return value is DBNull ? defaultValue : (T) value;
}

然后你将其称为:

string x = foo.GetField(reader, "field", "");

...该方法不具有特定于字符串的附加好处。

答案 1 :(得分:2)

这是一种方法:

public T GetField<T>(SqlDataReader dr, string fieldName)
{
    var value = dr.GetValue(dr.GetOrdinal(fieldName));
    return value is DBNull ? default(T) : (T) value;
}

这具有使用可空类型的额外好处。然后你将其称为:

string x = foo.GetField<string>(reader, "field") ?? "";

在这种情况下故意设计 - 如果通常你想要返回null以外的其他内容,那么带有默认设置的Jon版本更适合你。