无法将空值插入到列中...当该值不为空时。

3

在我的c#代码中,我有一个向数据库插入数据的操作,但是它抛出了异常。

无法将值NULL插入到列'BoxID',表'Moroccanoil_Replicated.dbo.Boxes';该列不允许为空。插入失败。

然而,当我调试这段代码时,我发现盒子实际上不是空的,另外,当我在SQL SM中测试相同的插入语句时,它完全正常工作。

编辑:

由于某些原因,根据分析器实际执行的查询如下:

exec sp_executesql 
  N'INSERT [dbo].[Boxes]([MasterBoxID], [DateTime], [Reported], [StationID])
  VALUES (NULL, @0, @1, @2)
  SELECT [BoxID]
  FROM [dbo].[Boxes]
  WHERE @@ROWCOUNT > 0 AND [BoxID] = scope_identity()',
  N'@0 datetime2(7),@1 bit,@2 int',@0='2015-11-30 13:37:46.4714394',@1=0,@2=7

有人知道为什么会出现这种情况吗?如何解决?
更多相关信息: - 异常发生在db.SaveChanges()调用上,而不是插入操作上。 - BoxID未定义为identity。
以下是带有插入值的调试模式代码截图: enter image description here 以下是同样可以正常工作的SQL插入语句截图: enter image description here

你是否在多个线程和/或并发异步上下文中使用了相同的上下文?这很可能是一个并发问题。 - Luaan
1
我会启动SQL分析器,观察相关的SQL查询运行情况,并将其与你的C#代码进行交叉检查。 - Andrew Savinykh
谢谢您提供这些图片。显然,这个特定的实体/实例没有这个问题。一定是另一个有这个问题。 - Andrew Savinykh
我添加了插入代码与值的一瞬间,我知道异常的含义,但我无法弄清楚为什么当值不为空时它被抛出。 - Ravid Goldenberg
2
很可能 EF 不会传递 ID 参数,因为它认为该值是由数据库创建的。这意味着您应该关闭此列的 DatabaseGeneratedOptions.Identity。 - DevilSuichiro
显示剩余14条评论
2个回答

7

如评论所提到:

最有可能的情况是 EF 不会传递 ID 参数,因为它认为该值由数据库创建。这意味着您应该关闭该列的 DatabaseGeneratedOptions.Identity 选项。

使用 DatabaseGeneratedOption.Identity,EF 不会将 ID 值传递给数据库,因为它认为该值是由 DBMS 给出的。这可能会导致此问题或 DbUpdateConcurrencyException,当它怀疑具有给定 Id 值的对象存在于数据库中时,但实际上是由 DBMS 修改的。


从EDMX中的Id列中删除StoreGeneratedPattern="Identity",然后它就可以工作了。+1 - Raj
这也是我的情况,我只需将 Identity 设置为 None,这样我就可以手动放置主键的值。 - Jed

1

正如所提到的,EF不会将ID列传递给数据库。如果您有一个不想要自动递增值的情况,下面是一个示例

public class PackingInventory
{

    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int ID { get; set; }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接