无法将空值插入到列“MaintenanceId”中,表“<tableName>”;该列不允许为空。插入失败 EF 6.1

7

我正在尝试在Azure上添加一个简单的条目至我的数据库,但是出于某种原因,该数据库没有为该条目生成主键。


以下是创建数据库和进行条目操作所使用的所有代码。


这是在控制台应用程序上使用EF 6.1实现的。

public BlizzardDbContext() : base("AzureSqlDb")
{
}

public DbSet<Maintenance> Maintenances { get; set; }

模型

public class Maintenance
{
    public Maintenance()
    {}

    public Maintenance(DateTime start, DateTime end, string info)
    {
        Start = start;
        End = end;
        Info = info;
    }

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int MaintenanceId { get; set; }

    public DateTime? Start { get; set; }

    public DateTime? End { get; set; }

    public string Info { get; set; }
}

保存更改时失败的测试

var context = new BlizzardDbContext();
context.Maintenances.Add(new Maintenance() {Start = DateTime.Now, End = DateTime.Now, Info = ""});
context.SaveChanges();

我知道这听起来很简单,我以前用过EF几次,但是这一次我无法弄清楚出了什么问题 下面是错误信息:

"无法将值NULL插入列“MaintenanceId”,表“.dbo.Maintenances”中,该列不允许为空。 插入失败。\r\n已终止该语句。"

enter image description here

更新:最终通过删除数据库并重新创建来解决此问题,我认为EF存在一些奇怪的问题,它没有正确地使用迁移更新数据库,因为在重新创建后,列被设置为Identity。


1
错误信息基本上就是问题所在。你要么没有传递值,因为你告诉EF数据库应该提供它,要么你正在传递值,因为该列不是标识列。在这种情况下,该列不是标识列(或已被关闭)。 - Erik Philips
@ErikPhilips 是的,我明白,但是从我的模型中可以看出,数据注释(我也尝试过使用流畅的API)告诉数据库它是PK列。这是从SQL Server对象资源管理器中访问列生成的SQL:ALTER TABLE [dbo].[Maintenances] ADD CONSTRAINT [PK_dbo.Maintenances] PRIMARY KEY CLUSTERED ([MaintenanceId] ASC); - Toxicable
1
那是一个 SQL Server 错误。不管你如何配置 EF,SQL Server 都告诉你它不是标识列。 - Erik Philips
2个回答

2

请确认MaintenanceId是否为数据库的标识键。

如果不是或您不确定,可以尝试以下选项:

更改

 [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

为了

[DatabaseGenerated(DatabaseGeneratedOption.None)]

.None - 这意味着“数据库不生成值。”


哦,哇,把它设置为 None 让它工作了,我感到很困惑,如果我不包括它,我会得到错误,但是当我转到 null 时它就可以工作了?因为 MaintenanceId 作为 PK。 - Toxicable
1
你可以在这里找到答案 :) https://dev59.com/M2Up5IYBdhLWcg3wCUGx - Shrutika Kalra
1
我需要以另一种方式来完成它,因为我的PK没有自动生成。当传递带有KEY填充的实体模型时,错误消息显示该属性为空,但实际上它不为空。因此,我必须使用[DatabaseGenerated(DatabaseGeneratedOption.None)],然后它就可以正常工作了。 - Piotr Kula

0

登陆到你的数据库,并验证MaintenanceId是否确实是自动生成的关键字。EF支持此功能,我怀疑在迁移过程中或者表的构建过程中发生了一些有趣的事情。

另外,请确保在你的DbContext类中没有禁用对象跟踪功能。这是默认开启的,所以除非你明确禁用了它,否则你不必担心它 :)


据我所知,由于它是Azure云数据库,我无法登录该数据库,但是我可以通过VS的SQL对象资源管理器访问它,这证实了它是(PK,int,not null),并且上面的评论中提到了创建它的代码。 - Toxicable
只要您可以访问Azure门户网站,就可以登录云数据库。如果需要,您可以使用SQL Server Management Studio。只需指向服务器的URL,并使用用户名/密码即可。也许您可以尝试删除密钥的第二个属性(DatabaseGenerated),看看是否有帮助?我从未使用过该属性,但仍然能够添加内容。 - Pedro G. Dias
好的,关于之前的错误,我以为设置 DatabaseGeneratedOption.None 可以解决它,但我忘了 int 的默认值是 0,这让它插入到了数据库中,所以不行。所以在按照你说的做后,我检查了数据库,发现该列似乎不是标识列,它是 PK,只不过不是标识列,有什么办法可以解决吗?最好使用 Code First。 - Toxicable
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Pedro G. Dias
好的,我明白了,这次我想EF出了一些奇怪的问题,导致它没有正确地应用迁移。所以我删除了数据库,并使用相同的代码重新创建了它,现在它实际上是一个身份列。 - Toxicable
太棒了。很高兴能帮助到您 :) - Pedro G. Dias

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