【问题标题】:IDENTITY_INSERT ON error with foreign keyIDENTITY_INSERT ON 外键错误
【发布时间】:2018-09-26 10:34:25
【问题描述】:

我正在尝试为某些条目手动设置 Id。

我有一个带有标识字段的客户类

  modelBuilder.Entity<Customer>().Property(f => f.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity);

在插入部分我有

    using (var transaction = ctx.Database.BeginTransaction())
    {
      ctx.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[Customers] ON");
      ctx.Customers.AddRange(customersList);
      ctx.SaveChanges();
      ctx.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[Customers] OFF");
      transaction.Commit();
    }

但我仍然遇到异常

必须为表中的标识列指定显式值 当 IDENTITY_INSERT 设置为 ON 或当 复制用户正在插入 NOT FOR REPLICATION 身份 列。

在我的异常的 StateEntries 中,我可以看到存储在另一个表(如“联系人”)中的所有字段似乎都是原因 customer.Contacts = new List&lt;Contact&gt; {new Contact {Name = "Test", … }}

我怎样才能让它工作?

【问题讨论】:

    标签: entity-framework entity-framework-6


    【解决方案1】:

    该错误消息具有误导性。您已成功打开 IDENTITY_INSERT,但 EF 仍在生成 INSERT 语句,假设键值将由 IDENTITY 列生成。

    所以您另外必须生成一个包含键值的 INSERT 语句。当然,您也可以使用 .ExecuteSqlCommand() 来执行 INSERT。或者您可以让 EF 执行此操作,但您必须使用该实体没有数据库生成的密钥的模型。 OnModelCreating 只为每个 ModelType 配置一次模型,因此您不能只在其中放置一个开关。

    相反,您可以创建 DbContext 的子类型用于播种,覆盖基础 DbContext 的实体配置。像这样:

    class Db_Seed: Db
    {
        public Db_Seed(string constr) : base(constr)
        {
            Database.SetInitializer<Db_Seed>(null);  //no initializer
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Customer>().Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        }
    }
    

    仍然必须将 IDENTITY_INSERT 设置为 on(因为表确实具有 IDENTITY),但在此上下文中,EF 不会生成假定服务器将生成密钥的 INSERT 语句。

    【讨论】:

    • 非常感谢。它正在工作,您的解释非常好。
    猜你喜欢
    • 2014-05-30
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-18
    • 2014-12-07
    相关资源
    最近更新 更多