如果value为null,如何将值返回到sqldatareader?

时间:2009-10-03 10:33:52

标签: sql sql-server vb.net sql-server-2008

我目前正在使用sql数据阅读器(在vb.net中)通过SQL Server 2008数据库中的存储过程提取文章对象。该对象的一部分包括以下两个属性:

theArticle.Truthfulness = ((myReader.GetInt32(myReader.GetOrdinal("Truthfulness"))))
theArticle.Relevance = ((myReader.GetInt32(myReader.GetOrdinal("Relevance"))))

我的问题是,真实性和相关性可能会返回一个空值,这会导致函数失效。

我想我理解为什么。我要求一个整数值(getin32),因为返回null失败。

如何容纳数据库中的空值,以免它倒下?

7 个答案:

答案 0 :(得分:18)

您可以使用.IsDBNull()检查给定的序号位置是否为空,然后执行某些操作 - 例如将您的值设置为-1或其他:

int myOrdinal = myReader.GetOrdinal("Truthfullness");

if(myReader.IsDBNull(myOrdinal))
{
  theArticle.Truthfulness = -1;
}
else
{
  theArticle.Truthfulness = myReader.GetInt32(myOrdinal);
}

正如Mike Hofer在答案中指出的那样,你也可以将所有这些逻辑包装成一个扩展方法:

public static class SqlDataReaderExtensions 
{
    public static int SafeGetInt32(this SqlDataReader reader, 
                                   string columnName, int defaultValue) 
    {
        int ordinal = reader.GetOrdinal(columnName);

        if(!reader.IsDbNull(ordinal))
        {
           return reader.GetInt32(ordinal);
        } 
        else
        {
           return defaultValue;
        }
    }
}

然后只使用“SafeGetInt32”方法:

  theArticle.Truthfulness = myReader.SafeGetInt32("Truthfullness", -1);

马克

答案 1 :(得分:2)

你检查过SqlDataReader.IsDBNull方法吗?可能类似于:

if(myReader.IsDBNull(myReader.GetOrdinal("Truthfulness"))
theArticle.Truthfulness = string.Empty;
else
theArticle.Truthfulness = ((myReader.GetInt32(myReader.GetOrdinal("Truthfulness"))))

答案 2 :(得分:1)

你知道,我一直在Oracle处理这个问题。为了清理代码,我编写了一组扩展方法来简化操作:

using System.Data.OracleClient;
public static class OracleDataReaderExtensions 
{
    public static int GetInt32(this OracleDataReader reader, string columnName, int defaultValue) 
    {
        return reader.GetInt32(reader.GetOrdinal(columnName)) != DbNull.Value ? 
               reader.GetInt32(reader.GetOrdinal(columnName)) : 
               defaultValue;
    }
}

为要返回的每种类型创建单独的重载。我主要使用string,int,date和decimal。记住YAGNI(您不需要使用阅读器支持的每种类型,只需使用您实际使用的类型。)

SQL Server这样的扩展类非常容易编写,并且可以大大简化您的工作。 相信我。我会欺骗你吗? :)

答案 3 :(得分:1)

这个通用版本可能有用:

    private T ValueOrDefault<T>(System.Data.IDataReader rdr, string columnName)
    {
        T vod = default(T);
        try
        {
            int idx = rdr.GetOrdinal(columnName);
            if (!rdr.IsDBNull(idx))
                return (T)rdr[idx];
        }
        catch (IndexOutOfRangeException) { }

        return vod;
    }

可以扩展以捕获InvalidCastException,还是使用Convert.ChangeType而不是强制转换?

答案 4 :(得分:0)

这是我们在SQLServer上使用的内容,它就像一个魅力:

...

  Dim X as Object = pbDr("TotAmt")  'dr is dim'ed as a DataReader

...

  Public Function pbDr(ByVal drName As String) As Object

    Dim SQLError As SqlClient.SqlException

    Dim IsNull As Boolean

    Dim Ordinal, DispNbr As Integer

    Try
      Ordinal = dr.GetOrdinal(drName)
      IsNull = dr.IsDBNull(Ordinal)
      If IsNull Then
        Dim Dbtype As String = dr.GetFieldType(Ordinal).ToString
        If Dbtype = "System.String" Then
          Return ""
        ElseIf Dbtype = "System.Int32" _
         OrElse Dbtype = "System.Double" _
         OrElse Dbtype = "System.Decimal" _
         OrElse Dbtype = "System.Int16" Then
          Return 0
        Else
          MsgBox("Print This Screen And Send To Support" _
           & "pbdr-Object = " & Dbtype, MsgBoxStyle.Critical)
          Return ""
        End If
      Else
        Return dr(Ordinal)
      End If

    Catch sqlerror
      Call DispSQLError(SQLError, "pbDr")
      pbDr = ""
    End Try

  End Function

答案 5 :(得分:0)

IsDbNull(int)通常比使用GetSqlInt32等方法慢,然后比较DBNull.Value或使用它自己的.IsNull喜欢:

    public static int Int32(this SqlDataReader r, int ord)
    {
        var t = r.GetSqlInt32(ord);
        return t.IsNull ? default(int) : t.Value;
    }

尝试了一些模板解决方案但到目前为止无济于事。问题是所有Sql类型(此处为SqlInt32)类型实际上是结构,而它们都有.Value属性C#没有真正的模板来处理它。它们也有自己的INullable接口,它只有.IsNull,并且与Nyllable&lt;&gt;不相容。

我怀疑人们需要完整的Sql类型作为C#模板,或者将ICOnvertible添加到它们中,以便能够只有一个或两个模板化方法。

如果有人可能有一个功能性技巧的想法或两个说出来:-)

答案 6 :(得分:-1)

现在,如果数据库返回它,您可能想要空值,因此您将使用Nullable<int>

public static class Extensions
{
    public static int? GetNullableInt32(this SqlDataReader reader, int ordinal)
    {
        if (reader.IsDBNull(ordinal))
            return null;

        return reader.GetInt32(ordinal);
    }

    public static long? GetNullableInt64(this SqlDataReader reader, int ordinal)
    {
        if (reader.IsDBNull(ordinal))
            return null;

        return reader.GetInt64(ordinal);
    }
}