You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将smallint转换为Int32?时引发Invalid Cast Exception问题求助

解决Nullable属性与DataReader中smallint类型的转换异常问题

咱们先把问题根源理清楚:数据库里的smallint对应.NET的Int16(也就是short类型),而你的模型属性是int?(Nullable)。当你直接从DataReader取出值赋值给int?属性时,因为DataReader返回的是装箱后的Int16对象,CLR没法自动把装箱的Int16直接转换成int?,所以就抛出了InvalidCastException。

下面给你几个实用的解决方案:

方案一:通用类型转换(推荐)

用Convert.ChangeType来自动适配类型转换,不管是smallint转int?,还是其他数值/Nullable类型的转换都能兼容,通用性最强:

foreach (var property in _properties) 
{
    property.SetValue(model, null, null);
    var lowerPropertyName = property.Name.ToLower();
    if (columnsInDataReader.Contains(lowerPropertyName)) 
    {
        var valueFromReader = _dataReader[property.Name];
        if (valueFromReader != DBNull.Value) 
        {
            // 把DataReader的值转换成属性对应的目标类型
            var convertedValue = Convert.ChangeType(valueFromReader, property.PropertyType);
            property.SetValue(model, convertedValue);
        }
    }
}

这个方法会自动处理数值类型的向上转换(比如short转int),同时也能完美适配Nullable类型的装箱需求。

方案二:针对Nullable类型的精准处理

如果想更针对性地处理Nullable属性,可以先获取它的底层非Nullable类型再转换,逻辑更清晰:

foreach (var property in _properties) 
{
    property.SetValue(model, null, null);
    var lowerPropertyName = property.Name.ToLower();
    if (columnsInDataReader.Contains(lowerPropertyName)) 
    {
        var valueFromReader = _dataReader[property.Name];
        if (valueFromReader != DBNull.Value) 
        {
            // 取出Nullable类型的底层类型,非Nullable类型则直接用自身
            Type targetType = Nullable.GetUnderlyingType(property.PropertyType) ?? property.PropertyType;
            var convertedValue = Convert.ChangeType(valueFromReader, targetType);
            property.SetValue(model, convertedValue);
        }
    }
}

方案三:特定类型的硬编码转换(局限性强)

如果你的场景里只有smallint转int?这一种类型问题,也可以直接读取为short再转成int,但这个方案只适用于单一场景,不推荐通用使用:

foreach (var property in _properties) 
{
    property.SetValue(model, null, null);
    var lowerPropertyName = property.Name.ToLower();
    if (columnsInDataReader.Contains(lowerPropertyName)) 
    {
        var valueFromReader = _dataReader[property.Name];
        if (valueFromReader != DBNull.Value) 
        {
            if (property.PropertyType == typeof(int?))
            {
                // 先读取为short,再转成int?
                short shortValue = _dataReader.GetInt16(_dataReader.GetOrdinal(property.Name));
                property.SetValue(model, (int?)shortValue);
            }
            else
            {
                property.SetValue(model, valueFromReader);
            }
        }
    }
}

最后提个小优化:用_dataReader.GetOrdinal(property.Name)代替直接索引列名,不仅能避免大小写匹配问题,性能也会更好一点。

内容的提问来源于stack exchange,提问作者Faheem Rasheed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:52:33