41

有没有更好/更清洁的方法来做到这一点?

int stockvalue = 0;
if (!Convert.IsDBNull(reader["StockValue"]))
    stockvalue = (int)reader["StockValue"];
4

13 回答 13

63

最短的(恕我直言)是:

int stockvalue = (reader["StockValue"] as int?) ?? 0;

解释:

  • 如果reader["StockValue"]int类型,则返回值,并且 "??" 运算符将返回结果
  • 如果reader["StockValue"]不是int类型(例如 DBNull),将返回 null,并且 "??" 运算符将返回值 0(零)。
于 2010-03-12T14:22:42.223 回答
31

我处理这个的方式是

int? stockvalue = reader["StockValue"] as int?;

非常简单,干净,一条线。如果由于某种原因我绝对不能有一个空值(我发现这通常是不好的推理,因为我宁愿知道一个值是否有意义,或者它是否被原始类型统一化)我会这样做:

int stockvalue = (reader["StockValue"] as int?).GetValueOrDefault(-1);
于 2010-03-12T14:17:57.133 回答
13

I wrote an extension method several days ago. By using it you could just do:

int? stockvalue = reader.GetValue<int?>("StockValue");

Here's the extension method (modify to fit your needs):

public static class ReaderHelper
{
    public static bool IsNullableType(Type valueType)
    {
        return (valueType.IsGenericType &&
            valueType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)));
    }

    public static T GetValue<T>(this IDataReader reader, string columnName)
    {
        object value = reader[columnName];
        Type valueType = typeof(T);
        if (value != DBNull.Value)
        {
            if (!IsNullableType(valueType))
            {
                return (T)Convert.ChangeType(value, valueType);
            }
            else
            {
                NullableConverter nc = new NullableConverter(valueType);
                return (T)Convert.ChangeType(value, nc.UnderlyingType);
            }
        }
        return default(T);
    }
}
于 2010-03-12T16:35:29.573 回答
10
int? stockvalue = (int?)(!Convert.IsDBNull(result) ? result : null);

一种可能的解决方案,以便您确保将 DBNull 传递到您的代码中。对于我们的小组,作为一种最佳实践,我们尝试在数据库中不允许 NULL 列,除非它确实需要。处理它的编码有更多的开销,有时只是重新考虑问题就不需要了。

于 2010-03-12T14:05:45.800 回答
7

虽然参考起来很方便reader["StockValue"],但效率不是很高。它也不是强类型的,因为它返回 type object

相反,在您的代码中,执行以下操作:

int stockValueOrdinal = reader.GetOrdinal("StockValue");
int? stockValue = reader.IsDbNull(stockValueOrdinal) ?
    null : 
    reader.GetInt32(stockValueOrdinal);

当然,最好一次获取所有序数,然后在整个代码中使用它们。

于 2010-03-12T14:18:27.237 回答
7

是的,您可以使用int? 这种方式,您可以使用默认值 null 而不是 0。由于 stockvalue 的结果可能为 0,因此不会混淆数据库是 0 还是 null。例如像这样(可以为空)我们有一个默认的初始化 -1 来表示没有赋值。就个人而言,我认为这有点危险,因为如果您忘记将其设置为 -1,则会出现很难追踪的数据损坏问题。

http://msdn.microsoft.com/en-us/library/2cf62fcy(VS.80).aspx

int? stockvalue = null;

if (!Convert.IsDBNull(reader["StockValue"]))
    stockvalue = (int)reader["StockValue"];

//Then you can check 

if(stockValue.HasValue)
{
  // do something here.
}
于 2010-03-12T13:58:10.670 回答
3
int stockvalue = reader["StockValue"] != DbNull.Value ? Convert.ToInt32(reader["StockValue"]) : 0;
于 2010-05-31T11:34:13.967 回答
1

这是一种方法。

int stockvalue = Convert.IsDbNull(reader["StockValue"]) ? 0 : (int)reader["StockValue"];

你也可以使用 TryParse

int stockvalue = 0
Int32.TryParse(reader["StockValue"].ToString(), out stockvalue);

让我们知道哪种方式适合您

于 2010-03-12T13:58:50.983 回答
1

您可以直接在您的数据库查询中进行此转换,从而完全避免这种特殊情况。

但我不会称其为“更清洁”,除非您可以在代码中始终使用该表单,因为您会通过从数据库返回“0”而不是 NULL 来丢失信息。

于 2010-03-12T13:59:18.093 回答
0
int? stockValue = reader["StockValue"] == null || reader["StockValue"] == DBNull.Value ? null : (int?)reader["StockValue"];
于 2010-03-12T16:42:27.997 回答
0

我的项目中有以下两种扩展方法:

    public static T GetValueSafe<T>(this IDataReader dataReader, string columnName, Func<IDataReader, int, T> valueExtractor)
        where T : class 
    {
        T value;
        if (dataReader.TryGetValueSafe(columnName, valueExtractor, out value))
        {
            return value;
        }

        return null;
    }

    public static bool TryGetValueSafe<T>(this IDataReader dataReader, string columnName, Func<IDataReader, int, T> valueExtractor, out T value)
    {
        int ordinal = dataReader.GetOrdinal(columnName);

        if (!dataReader.IsDBNull(ordinal))
        {
            // Get value.
            value = valueExtractor.Invoke(dataReader, ordinal);

            return true;
        }

        value = default(T);
        return false;
    }

用法可以是这样的:

string companyName = dataReader.GetValueSafe("CompanyName", (reader, ordinal) => reader.GetString(ordinal));
于 2010-03-12T14:39:44.783 回答
0

使用Nullable<int>类型...int?简称

于 2010-03-12T13:58:21.540 回答
0

并不真地。您可以将其封装在一个方法中:

public int getDBIntValue(object value, int defaultValue) {
  if (!Convert.IsDBNull(value)) {
    return (int)value;
  }
  else {
    return defaultValue;
  }

并这样称呼它:

stockVaue = getDBIntVaue(reader["StockValue"], 0);

或者,您可以coalesce在查询中使用强制返回值非空。

编辑 - 根据收到的评论更正愚蠢的代码错误。

于 2010-03-12T13:59:46.580 回答