IDENTITY_INSERT during seeding with EntityFramework 6 Code-First

后端 未结 9 694
遥遥无期
遥遥无期 2020-12-05 10:19

I have an entity that has an Auto-identity (int) column. As part of the data-seed I want to use specific identifier values for the \"standard data\" in my syste

相关标签:
9条回答
  • 2020-12-05 11:06

    According to this previous Question you need to begin a transaction of your context. After saving the change you have to restate the Identity Insert column too and finally you must have to commit the transaction.

    using (var transaction = context.Database.BeginTransaction())
    {
        var item = new ReferenceThing{Id = 418, Name = "Abrahadabra" };
        context.IdentityItems.Add(item);
        context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT Test.Items ON;");
        context.SaveChanges();
        context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT [dbo].[User] OFF");
        transaction.Commit();
    }
    
    0 讨论(0)
  • 2020-12-05 11:13

    For future Googlers, I found the answers suggesting some conditional logic in the OnModelCreating() didn't work for me.

    The main issue with this approach is EF caches the model, so it's not possible to switch identity on or off in the same app domain.

    The solution we adopted was to create a second derived DbContext which allows identity insert. This way, both models can be cached, and you can use the derived DbContext in the special (and hopefully) rare cases when you need to insert identity values.

    Given the following from @RikRak's question:

    public class ReferenceThing
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        public string Name { get; set; }
    }
    
    public class MyDbContext : DbContext 
    {
        public DbSet<ReferenceThing> ReferenceThing { get; set; }   
    }
    

    We added this derived DbContext:

    public class MyDbContextWhichAllowsIdentityInsert : MyDbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
    
            modelBuilder.Entity<ReferenceThing>()
                        .Property(x => x.Id)
                        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
        }
    }
    

    Which would then be used with the Seeder as follows:

    var specialDbContext = new MyDbContextWhichAllowsIdentityInsert();
    
    Seeder.Seed(specialDbContext);
    
    0 讨论(0)
  • 2020-12-05 11:14

    Say you have a table named Branch with a column of type integer named BranchId. By convention with SQL Server, EF will assume that a column with of type integer is an Identity column.

    So it will automatically set the column's Identity Specification to:

    • (Is Identity) Yes
    • Identity Increment 1
    • Identity Seed 1

    If you want to seed an entity with id values that are assigned, then use the DatabaseGeneratedOption as follows:

    public class Branch
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int BranchId { get; set; }
        public string Description { get; set; }
    }
    

    You can then seed the data and assign whatever value you want to the BranchId.

    0 讨论(0)
提交回复
热议问题