【问题标题】:EF Code First giving me error Cannot insert explicit value for identity column in table 'People' when IDENTITY_INSERT is set to OFF. [duplicate]当 IDENTITY_INSERT 设置为 OFF 时,EF Code First 给我错误无法为表“People”中的标识列插入显式值。 [复制]
【发布时间】:2011-01-13 16:34:04
【问题描述】:

我正在试用 Entity Framework 4 的 Code First (EF CodeFirst 0.8),但遇到了一个简单模型的问题,该模型在 PersonProfile 之间具有 1 0..1 关系.以下是它们的定义:

public class Person
{
    public int PersonId { get; set; }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime? DOB { get; set; }

    public virtual Profile Profile { get; set; }
}

public class Profile
{
    public int ProfileId { get; set; }
    public int PersonId { get; set; }
    public string DisplayName { get; set; }

    public virtual Person Person { get; set; }
}

数据库上下文如下所示:

public class BodyDB : DbContext
{
    public DbSet<Person> People { get; set; }   
}

我没有为Profile 定义DbSet,因为我认为People 是它的聚合根。当我尝试使用此代码添加新的Person - 甚至没有Profile 时:

public Person Add(Person newPerson)
{
    Person person = _bodyBookEntities.People.Add(newPerson);
    _bodyBookEntities.SaveChanges();
    return person;
}

我收到以下错误:

当 IDENTITY_INSERT 设置为 OFF 时,无法为表“People”中的标识列插入显式值。

当我调用People.Add() 时,newPerson 对象的PersonId 属性具有0。数据库表是PeopleProfilesPersonIdPeople 的PK,是一个自增身份。 ProfileIdProfiles 的 PK 并且是一个自动增加的身份。 PersonIdProfiles 的非空 int 列。

我做错了什么?我认为我遵守了所有 EF Code First 的配置规则约定。

【问题讨论】:

  • 我可能错了,但我相信标识列的默认约定是一个名为 Id 的属性,您是否尝试将 PersonId 更改为仅 Id
  • 其实,我原本把所有的PK列都简单命名为Id。为了解决这个问题,我更改了它们,如我的帖子中所示。 Scott Gu 的原始代码帖子首先将 DinnerID 作为餐桌的主键 - weblogs.asp.net/scottgu/archive/2010/07/16/…
  • 发生此错误的另一种方式是,如果您从另一个上下文中获取 [One] 实体,而不是在 [Many] 实体中设置它。 IE。这会得到错误:ParentEntity parent;using (var db = new Context()) { parent = db.Parents.First(); }using (var db = new Context()) { db.Children.Add(new Child {Parent = parent});db.SaveChanges(); } 要修复,只需在第二个上下文块中添加db.Children.Attach(parent)

标签: entity-framework entity-framework-4


【解决方案1】:

我收到以下错误: 当 IDENTITY_INSERT 设置为 OFF 时,无法为表“People”中的标识列插入显式值。

我认为 IDENTITY_INSERT 是关闭的自动增量功能。 所以,检查数据库中的 PersonId 字段,看看它是否是一个身份。

此外,也许这也能解决您的问题。

[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int PersonId { get; set; }

【讨论】:

  • 遇到了同样的问题,我通过在 DbContext 中的 OnModelCreating 覆盖上设置 DatabaseGeneratedOption.Identity 来修复它
  • 我也有同样的问题,我在实体和 DbContext 上设置了 DatabaseGeneratedOption.Identity。如何解决这个问题?我的 Db 在 Azure 中本地化。
【解决方案2】:

如果您执行以下步骤,就会发生这种情况:

  1. 在表上创建非身份 PK 字段。
  2. 从该表推断实体模型。
  3. 返回并将 PK 标识设置为 true。

实体模型和数据库不同步。刷新模型将修复它。我昨天不得不这样做。

【讨论】:

  • 但是,我使用的是 EF4 的 Code First 模型;没有 EDMX 文件。 EF 通过模型类的命名约定推断 CSDL 到 SSDL 的映射。还有一个流利的接口用于覆盖约定——我没有在这里使用它,因为我认为在这个特定的实例中我不需要它。
  • 所以,这里的基本问题是 EF 应该生成一个没有 PersonId 的 INSERT 语句,但事实并非如此(Profiler 也可能有帮助)。我对 EF4 不够熟悉,无法知道身份标志的维护位置,但是在您的模型中的某处,模型不知道 PersonId 是 Identity。对不起,我没有更多的帮助。
  • 好一个克里斯,这正是我的问题。编码太晚而咖啡太少是我这个错误的原因!干杯:)
  • 如何刷新模型?
  • 在实体图中右键单击并选择“从数据库更新模型”。然后你会得到一个对话框,你可以点击“完成”。
【解决方案3】:

如果您使用的是 EF Code First,那么除了按照其他人的建议将 [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 注释属性添加到 model.cs 文件之外,您还需要对 modelMap.cs 文件(流畅的映射指令)进行相同的有效更改:

更改自:

this.Property(t => t.id)
   .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

到:

this.Property(t => t.id)
   .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

(我使用 EF Power Tools 生成实体模型和默认映射文件,然后将一个 Id 列转换为主键列并在 Sql Server 中将其设置为 IDENTITY,因此,我必须更新属性和默认映射文件。)

如果你不在两个地方都改变它,你仍然会得到同样的错误。

【讨论】:

    【解决方案4】:

    当 PrimaryKey 和 ForeignKey 是同一列时,您的情况让我想起了我使用 EF Code First 时遇到的情况。

    没有直接刷新模型的方法,但是可以分两步达到相同的效果。

    1. 注释掉 Profile 类中的 ProfileId。重新编译并更新数据库。
    2. 取消注释配置文件 ID,添加 DatabaseGeneratedAttribute 并再次更新数据库。

    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.None), Key]

    这样生成的 ProfileId 列就变成 Key without Identity。

    【讨论】:

    • 这适用于代码优先迁移吗?脚手架不会为我生成。
    • 它不会起作用,因为迁移会提示添加 Id。除非您提供 ID,否则它将不允许您继续。l
    【解决方案5】:

    我没有遇到这个问题直到我添加了一个复合键,所以一旦我有 2 个主键,EF 6.x.x 就会发生这种情况

    Identity Specification 设置为 true 的键“Id”上,我需要 添加

    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    

    现在的模型属性:

    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    [Key, Column("Id", Order = 1)]
    public int Id { get; set; }
    
    [Key, Column("RanGuid", Order = 2)]
    public string RanGuid { get; set; }
    

    【讨论】:

      【解决方案6】:

      如果您像我一样使用 EF 核心和流畅的界面,我发现我用来从现有数据库创建模型的 Scaffold-DbContext 实用程序会为我的列生成这样的一行:

      entity.Property(e => e.id).ValueGeneratedNever();
      

      在我更改了将 IDENTITY 属性添加到我的 id 的数据库之后,我不得不更改以下行:

      entity.Property(e => e.id).ValueGeneratedOnAdd();
      

      除了将 [DatabaseGeneratedAttribute(DatabaseGeneratedOption.None), Key] 装饰器添加到我的模型类中的 id 字段。

      我什至不确定后者是否有必要。用前一个修复解决后,我没有尝试删除它。

      【讨论】:

      • 删除这个 ValueGeneratedNever 为我工作
      • 大多数情况下,您可以致电context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Person ON"); _context.SaveChanges(); context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.Person OFF");docs.microsoft.com/en-us/ef/core/saving/…。似乎有一个关于使用 EF Core 切换身份插入的功能请求。我们必须等待它。
      【解决方案7】:

      为了搜索者的利益:我收到此错误,但上述修复无效。这是由于我的错误。

      在我的桌子上,我有一个 Guid 主键(非聚集)和一个 int 索引。

      尝试使用“博客”信息作为导航属性更新“帖子”时发生错误。请参阅以下课程:

      public class Blog
      {
          public Guid BlogId { get; set; }
      
          public int BlogIndex { get; set; }
      
          // other stuff
      }
      
      public class Post
      {
          public Guid PostId { get; set; }
      
          public int PostIndex { get; set; }
      
          // other stuff
      
          public Blog Blog { get; set; }
      }
      

      问题在于,当我将 DTO 转换为模型时,BlogId 被更改为 new Guid()(我在映射中出错了)。产生的错误与此问题中详述的错误相同。

      要修复它,我需要在插入时检查数据是否正确(不是)并修复数据的错误更改(在我的情况下,映射损坏)。

      【讨论】:

      • 对我来说也是如此。我没有以正确的顺序插入我的数据,在 PK 模型之前插入 FK 模型,因此在身份映射中出错。
      【解决方案8】:

      在 EF6 中遇到此错误,查看了数据库,并且将 Identity Specification 设置为 Yes 时一切正常。然后我删除了不同的迁移并从当前模型进行了一次新的迁移,然后一切都开始工作了。最快的解决方案,因为该应用程序尚未上线且仍在开发中。

      无法为表中的标识列插入显式值 IDENTITY_INSERT 设置为 OFF 时的“测试”。

      【讨论】:

        【解决方案9】:

        这里是解决方案。另请参阅附件以获取更多帮助。

        导航到您的 EF 模型“.edmx”文件 >> 打开它 >> 现在右键单击图表并选择“从数据库更新模型”。

        这将解决此问题,因为您在创建 EF 模型后将 PK 设置为数据库中的身份。

        help to recreate steps stated above

        【讨论】:

          【解决方案10】:

          在我的情况下,似乎 EF 不喜欢 INT 身份字段以外的其他类型 - 我的是 BYTE (SQL 端的 TINYINT)。

          由于我能够在 SQL 上更新我的项目并将其更改为 INT,在 VisualStudio 上重新运行逆向工程代码优先后,错误立即停止发生。

          【讨论】:

            【解决方案11】:

            在我的情况下,似乎 EF 不喜欢除 INT 标识字段之外的其他类型 - 我的是 BYTE(SQL 端的 TINYINT)。

            我在使用 tinyint 类型的 PK 时也遇到了这个错误。并不是 EF 不喜欢它,似乎与其他情况不同,您必须在配置中这样指定:

            this.Property(t => t.TableID).HasColumnName("TableID").HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            

            【讨论】:

              猜你喜欢
              • 2021-07-02
              • 2017-10-26
              • 1970-01-01
              • 2016-05-13
              • 2012-11-10
              • 2019-03-10
              • 2016-01-20
              • 2018-06-29
              • 2016-08-18
              相关资源
              最近更新 更多