首页 文章

异常:无法将null值分配给类型为System.Int32的成员,该类型是不可为空的值类型

提问于
浏览
1

有人可以解释为什么在以下LINQ查询中发生此异常:

return (from c in dc.Classifications
                where c.Id == classificationId
                select new Classification()
                {
                    Description = c.Description,
                    ParentId = Convert.ToInt16(c.ParentId),
                }).Single<Classification>();

dc是datacontext,Classification是一个包含int属性ParentId的类 . ParentId列是来自Sql Server数据库的可空int . 如果ParentId字段在数据库中为null,则该语句将返回InvalidOperationException .

换句话说,为什么上面的查询失败并且'int y = Convert.ToInt16(null);'
工作?

3 回答

  • 1

    如果 c.PartentId 可以是 null ,则 Convert.ToInt16(null) 会抛出异常 .

    既然你指出 Classification.ParentId 是一个int,你是否有理由使用 Convert.ToInt16 来缩短它?你不想要ToInt32吗?就此而言,为什么转换呢?只是:

    ParentId = c.ParentId ?? 0
    

    ...而且只是为了挑选,从技术上讲,你不需要在Linq表达式的末尾指定你的类型:

    .Single<Classification>()
    

    你可以省略它,因为它是由编译器决定的,只是这样做:

    .Single()
    

    Update:

    哦,我明白了,对不起,我错误地读了你原来的问题 . 问题是为什么:

    int y = Convert.ToInt16(null);
    

    工作,而Linq2Sql表达式中的相同内容抛出异常 .

    我没有一个很好的答案,除了指出虽然表达式在代码中看起来相同,但实际上是由2个不同的Linq实现处理 . (与界面大致相同,可以有不同的后备实现) .

    如果是:

    int y = Convert.ToInt16(null);
    

    您正在直接调用Convert.ToInt16 . 这似乎将null转换为 default<T> ,其中T是所需的类型(因此在这种情况下返回0) .

    但是,当在Linq2Sql表达式中使用时,表达式及其投影将被移交给Linq2Entities或Linq2Sql进行处理 . 那个地方可能只有一个错误 . 用作基本的Linq2Objects(或者你想要的任何东西)它实际上似乎工作正常:

    [TestMethod] // test passes
    public void TestLinqToObjects()
    {
      var stuff = new List<int?>() { null };
      var y = (from x in stuff
               select Convert.ToInt32(x))
               .First();
      Assert.AreEqual(0, y);
    }
    

    上面的“选择”工作,但是对Linq2Sql或EntityFramework集合使用相同的Linq表达式将导致Linq处理器的不同实现来处理表达式,并且它可能做一些不同的尝试来表达表达式,或者转向其中一些是SQL语句,或者只是有其他实现没有的错误 .

    我知道这并没有真正解决你的问题,但它可能有助于解释它?

  • 0

    假设您希望在数据库中为NULL时将0设为 ParentId

    return (from c in dc.Classifications
                where c.Id == classificationId
                select new Classification()
                {
                    Description = c.Description,
                    ParentId = Convert.ToInt16(c.ParentId ?? 0),
                }).Single<Classification>();
    

    我的回答还假设, Classifications.ParentId 的类型为 Nullable<int> / int? ,如果数据库中的列为NULL,则其值为 null .

    我唯一改变的是转换中的 ?? 0 部分 . 如果 c.ParentIdnull ,则使用 0 ,否则为 c.ParentId . 有关详细信息,请参阅?? Operator .

  • 2

    c.ParentId的类型为 int?

    您对Convert.ToInt16的调用会以两种方式被破坏;它在null上失败(如此处所示),如果ParentId大于short.MaxValue或小于short.MinValue,则失败 .

    那为什么打电话?去掉它 . 另外,将 Single<Classification>() 替换为 SingleOrDefault() ,以便在适当时返回null .

相关问题