将泛型类与 SqlDataReader GetValue 一起使用

本文关键字:一起 GetValue SqlDataReader 泛型类 | 更新日期: 2023-09-27 18:30:58

我有这段代码,可以很好地处理没有 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>因为字符串没有参数为 0 的构造函数。

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

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

但答案是它们是模棱两可的定义,因为 T 还包括字符串,即使应用了限制。

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

我错过了什么吗?

谢谢!

将泛型类与 SqlDataReader GetValue 一起使用

最后一个方法将失败,因为它尝试声明一个名为 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", "");

。还有一个额外的好处,即该方法不是特定于字符串的。

这里有一种方法:

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

这具有使用可为 null 类型的额外好处。然后你可以称之为:

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

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