'无法将值NULL插入表'UserDB.dbo.Users'的'UserId'列中;列不允许为空。 INSERT失败

时间:2018-10-05 14:12:22

标签: asp.net sql-server asp.net-mvc entity-framework

使用ASP.NET MVC和实体框架在SQL Server中保存数据时出现错误。该错误表明它无法插入具有空主键的数据。我已经将IsIdentity设置为自动递增1。

这是代码:

public ActionResult Index(User user)
{
    if (ModelState.IsValid) 
    {
        if (user.UserId != 0) 
            db.Entry(user).State = EntityState.Modified;
        else
            user.IsActive = true;

        db.Users.Add(user);
        db.SaveChanges();
    }

    return View(user);
}

1 个答案:

答案 0 :(得分:1)

这是SQL事情。如果您有一个包含列IDName的表,其中ID是主键,并带有标识设置以及NOT NULLUNIQUE约束,则插入语句必须如下所示:

INSERT INTO [table] (name) values ('Vivek')

这将自动处理ID列。但是,这将失败:

INSERT INTO [table] (ID, name) values (NULL, 'Vivek')

它试图告诉数据库您希望ID列的值为NULL。当然,由于NOT NULL约束,这失败了。它与第一个选项不同,在第一个选项中,允许数据库使用标识来设置ID列的值。

现在继续(大概)C#代码。这里有一个User对象,它还没有ID值,因为您只是在创建它。此User类型(未共享,所以我只能猜测)可能具有一个简单的int的{​​{1}}值,并且此int尚未初始化(意味着该值是{{ 1}},即ID)。现在,您要插入记录。 Linq将生成类似于以下内容的SQL语句:

default(int)

但是在过去的某个地方,您运行了相同的代码,并且具有相同的0值,因此表中已经有了该ID值的另一条记录。这将导致UNIQUE约束失败,并且SQL Server(正确地)拒绝了SQL语句。

要解决此问题,我们将通过更改此模型上的ID值以使用INSERT INTO [table] (ID, name) values (0, 'Vivek') 类型来开始。我知道您可能不希望到处都这样,因此,如果有帮助,您实际上可以在此处使用其他类(0)。这将为生成的SQL中的ID列提供一个真正为空(NULL)的值。

但是现在我们遇到了一个新问题:我们最后得到了一个插入,就像我的第二个示例一样。我们看到这还不够;我们需要告诉linq根本不要在生成的SQL中使用该列。您可以通过从特殊的int?类中完全删除ID属性来完成此操作。

但是我们可以做得更好。 Linq允许我们使用称为attributes的东西来装饰属性,这些属性会影响生成的SQL。您可以在这里告诉它如何处理ID列:

NewUser

可以与现有的NewUser类一起使用,而无需创建全新的类型。