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

发布于 2024-10-27 05:41:33 字数 609 浏览 2 评论 0原文

有人可以解释为什么在以下 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 是数据上下文,Classification 是包含 int 属性 ParentId 的类。 ParentId 列是来自 Sql Server 数据库的可为 null 的 int。如果数据库中的 ParentId 字段为 null,则该语句将返回 InvalidOperationException。

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

Can someone explain why this exception is occuring the in the following LINQ query:

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

dc is the datacontext, Classification is a class containing the int property ParentId. The ParentId column is a nullable int from a Sql Server database. In the case of the ParentId field being null in the database, the statement returns an InvalidOperationException.

In other words, why does the above query fail and
'int y = Convert.ToInt16(null);'
work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

橙幽之幻 2024-11-03 05:41:33

假设当数据库中为 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? 如果该列在数据库中为 NULL,则其值为 null

我唯一改变的是 ?? 0 部分在转换中。如果 c.ParentIdnull,则使用 0,否则使用 c.ParentId。请参阅 ??运营商了解更多信息。

Assuming that you want to have 0 as ParentId when it is NULL in the database:

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

My answer also assumes, that Classifications.ParentId is of type Nullable<int>/int? and its value is null if the column is NULL in the database.

The only thing I changed, was the ?? 0 part in the convert. It uses 0 in case c.ParentId is null and c.ParentId otherwise. See ?? Operator for more info.

相权↑美人 2024-11-03 05:41:33

如果 c.PartentId 可以为 null,则 Convert.ToInt16(null) 将引发异常。

既然您指出 Classification.ParentId 是一个 int,那么您使用它是否有原因
Convert.ToInt16 使其变短?您不想用 ToInt32 代替吗?就此而言,为什么要转换呢?简单地说:

ParentId = c.ParentId ?? 0

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

.Single<Classification>()

您可以省略它,因为它是由编译器确定的,只需执行以下操作:

.Single()

更新:

哦,我明白了,很抱歉我误读了您原来的问题。问题实际上是为什么:

int y = Convert.ToInt16(null);

有效,而 Linq2Sql 表达式中的相同内容会引发异常。

我对此没有一个很好的答案,只是指出虽然表达式在代码中看起来相同,但它们实际上是由 2 个不同的 Linq 实现处理的。 (就像接口可以有不同的支持实现一样)。

在以下情况下:

int y = Convert.ToInt16(null);

您正在直接调用 Convert.ToInt16。这似乎将 null 转换为 default ,其中 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 语句,或者可能只是存在其他实现没有的错误。

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

If c.PartentId can be null, then Convert.ToInt16(null) would throw an exception.

Since you indicate that Classification.ParentId is an int, is there a reason you are using
Convert.ToInt16 to make it a short instead? Wouldn't you want ToInt32 instead? For that matter, why convert at all? simply:

ParentId = c.ParentId ?? 0

...and just to nit-pick, technically you don't need to specify your type at the end of that Linq expression:

.Single<Classification>()

you can omit that, since it is determined by the compiler, and just do:

.Single()

Update:

Oh I see, I'm sorry I mis-read your original question. The question is really why does:

int y = Convert.ToInt16(null);

work, while the same thing in a Linq2Sql expression throws an exception.

I don't have a great answer to that, other than to point out that while the expressions look the same in code,t hey are actually handled by 2 differnet Linq implementations. (Much the same as an interface can have different backing implementations).

In the case of:

int y = Convert.ToInt16(null);

You are making a direct call to Convert.ToInt16. This seems to convert a null into default<T> where T is the desired type (so it return 0 in this case).

However when used in a Linq2Sql expression, the expression and its projection are handed off to Linq2Entities or Linq2Sql to process. There could just be a bug in that stuff somewhere. Used as a basic Linq2Objects (or whatever you want to call it) it actually seems to work OK:

[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);
}

The above "select" works, however putting the same Linq expression against a Linq2Sql or EntityFramework collection would cause a different implementation of the Linq processor to handle the expression,a nd it might do something different to try to optemise the expression, or to turn some of it into a SQL statement, or could just have bugs that the other implementations don't.

I know that doesn't really solve your issue, but it might help to explain it?

×纯※雪 2024-11-03 05:41:33

c.ParentId 的类型为 int?

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

为什么会有这个电话?将其删除。另外,将 Single() 替换为 SingleOrDefault(),以便它可以在适当的时候返回 null。

c.ParentId is of type int?

Your call to Convert.ToInt16 is then broken in two ways; it fails on null (as here) and it fails if ParentId is greater than short.MaxValue or smaller than short.MinValue.

Why is that call there? Remove it. Also, replace Single<Classification>() with SingleOrDefault() so that it can return null when appropriate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文