11

我们如何从 Sql Data Reader 读取整数空值

SqlDataReader reader = cmd.ExecuteReader();
if (reader.Read() == true)
{
    mb.Id = (int)reader["Id"];
    mb.Mem_NA = (string)reader["Mem_NA"];
    mb.Mem_ResAdd4 = reader["Mem_ResAdd4"] == System.DBNull.Value ? null : (string)reader["Mem_ResAdd4"];
    //
   mb.Mem_ResPin = reader["Mem_ResPin"] as  int? ?? default(int);
  // shows the error "Object cannot be cast from DBNull to other types."
 }

mb.Mem_ResPin 无法从阅读器读取

 CREATE TABLE [dbo].[Mem_Basic] (
[Id]          INT           IDENTITY (1, 1) NOT NULL,
[Mem_NA]      VARCHAR (100) NOT NULL,
[Mem_ResAdd4] VARCHAR (100) NULL,
[Mem_ResPin]  INT           NULL,
PRIMARY KEY CLUSTERED ([Id] ASC)
);
4

8 回答 8

14

只需转换它,就像您在上一行中所做的那样

mb.Mem_ResAdd4 = reader["Mem_ResAdd4"] == System.DBNull.Value ? null : (string)reader["Mem_ResAdd4"];
//
    mb.Mem_ResPin = reader["Mem_ResPin"]== System.DBNull.Value ? default(int):(int)reader["Mem_ResPin"]
于 2013-08-30T10:34:03.060 回答
9

我对所有 DB 强制转换使用通用扩展方法:

public static T? DbCast<T>(this object dbValue)
        where T : struct
    {
        if (dbValue == null)
        {
            return null;
        }
        if (dbValue is System.DBNull)
        {
            return null;
        }
        T? value = dbValue as T?;
        if (value != null)
        {
            return value;
        }
        var conv = dbValue as IConvertible;
        if (conv != null)
        {
            value = (T)conv.ToType(typeof(T), CultureInfo.InvariantCulture);
        }
        return value;
    }

它试图处理我们迄今为止遇到的每一种情况。根据需要调整条件。

用法:

int? value = reader["Mem_ResAdd4"].DbCast<int>()
于 2013-08-30T10:39:37.070 回答
5

编写一个简单的包装器,例如作为扩展方法并检查IsDBNull内部:

public static int SafeGetInt(this SqlDataReader reader, string colName)
{
    var colIndex = reader.GetOrdinal(colName);
    return !reader.IsDBNull(colIndex) ? reader.GetInt32(colIndex) : default(int);
}

用法:

var result = reader.SafeGetInt(colName);
于 2013-08-30T10:39:20.473 回答
3

也许试试这个扩展:

public static class Helper
{
    public static T GetSafe<T>(this SqlDataReader reader, string name)
    {
        var value = reader[name];
        return value == DBNull.Value ? default(T) : (T) value;
    }
}

并像这样使用:

        if (reader.Read())
        {
            Mb mb = new Mb();
            mb.Id = reader.GetSafe<int>("Id");
            mb.Mem_NA = reader.GetSafe<string>("Mem_NA");
            mb.Mem_ResAdd4 = reader.GetSafe<string>("Mem_ResAdd4");

            mb.Mem_ResPin = reader.GetSafe<int>("ResPin");
        }
于 2013-08-30T10:41:04.257 回答
3

您可以使用 SqlDataReader.GetSqlInt32来处理Nullable<int>

SqlInt32 resPin = reader.GetSqlInt32(reader.GetOrdinal("Mem_ResPin"));
mb.Mem_ResPin = resPin.IsNull ? (int?) null : resPin.Value;
于 2013-08-30T10:42:51.530 回答
2

这里有几种方法。不幸的是,DBNull这很麻烦——APIreader[name]返回一个object可能是你的值,或者可能是DBNull.Value——所以你必须检查那个 ( is) 并处理它。另一种方法是使用reader.IsDBNull(ordinal)API,但您会注意到:这需要一个序数(列索引)而不是名称。在任何一种情况下,您都可以添加实用程序方法之类的东西来帮助:

static object Read(IDataReader reader, string name)
{
    var val = reader[name];
    return val is DBNull ? (object)null : val;
}

然后(例如):

mb.Mem_ResPin = (int?)Read(reader, "Mem_ResPin")

然而,再一次:像“dapper”这样的工具可能会让你更容易做到这一点;一个单一的Query<T>(tsql, args).SingleOrDefault()将处理所有这些,包括空值、Nullable<T>和一系列其他场景。

于 2013-08-30T10:38:11.280 回答
1

比较是反对DBNull

var resPin = reader["Mem_ResPin"];
if(!Convert.IsDBNull(resPin))
  mb.Mem_ResPin = resPin as int?;
else
  mb.Mem_ResPin = new Nullable<int>();
于 2013-08-30T10:34:08.063 回答
1
public static class SqlDataReaderExtensions
{
    public static T Value<T>(this SqlDataReader reader, string name, T defaultValue = default)
    {
        var val = reader[name];

        if (val == DBNull.Value)
            return defaultValue;

        return (T)val;
    }
}
于 2020-06-19T13:46:07.820 回答