首页 > 解决方案 > “当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'x' 中插入标识列的显式值” - 使用嵌套自定义对象插入记录

问题描述

我收到错误“当 IDENTITY_INSERT 设置为 OFF 时,无法在表 'UserPermission' 中插入标识列的显式值”尝试插入如下记录:

dbContext.User.Add(someUser);
dbContext.SaveChanges();

话虽如此,User 文件将自定义类 UserPermission 作为其参数之一,并且someUserUserPermission 不为 null 并且具有设置的 ID 参数。为什么会发生这种情况,是否可以避免出现此错误,而无需在我的 User 模型中显式添加 UserPermissionID 外键参数并将 UserPermission 参数设置为 null?

提前致谢。

标签: entity-frameworkentity-framework-coreasp.net-core-mvc

解决方案


当反序列化在对象图中具有相关实体的实体然后尝试添加它们时,通常会发生此问题。UserPermission 可能是在数据库中设置有身份 PK 的现有记录,但 EF 似乎无法在实体定义中识别它。(即设置为DatabaseGenerated(DatabaseGeneratedOption.Identity)。如果是这样,您很可能会看到一个不同的问题,即创建了一个全新的重复 UserPermission。

如果 someUser 及其关联的 someUser.UserPermission 是反序列化实体,那么您需要做一些工作以确保 EF 知道 UserPermission 是现有行:

void AddUser(User someUser)
{
    var existingPermission = _context.UserPermissions.Local
        .SingleOrDefault(x => x.UserPermissionId == someUser.UserPermission.UserPermissionId);
    if (existingPermission != null)
        someUser.UserPermission = existingPermission;
    else
        _context.Attach(someUser.UserPermission);

    _context.Users.Add(someUser);
    _context.SaveChanges();
}

简而言之,当使用 DbContext 可能未跟踪的分离实体时,我们需要检查该LocalID 的任何现有跟踪实例的状态。如果我们找到一个,我们用分离的参考代替跟踪的参考。如果我们没有找到一个,我们在添加我们的用户之前附加分离的一个。

这仍然不完全安全,因为它假定引用的 UserPermission存在于数据库中。如果出于任何原因发送了不存在的 UserPermission(行已删除或伪造数据),您将在保存时收到异常。

传递分离的实体引用起初似乎是一个简单的选项,但您需要为分离实体中的每个引用执行此操作。如果您只是Attach在没有首先检查的情况下调用,它可能会工作,直到您遇到在运行时它不起作用的场景,因为上下文恰好已经在跟踪一个实例。


推荐阅读