Stig Schmidt Nielsson
Stig Schmidt Nielsson

Reputation: 1687

How to control primary key values when seeding data with Entity Framework codefirst

I am creating an asp.net mvc4 site using entity framework 5 with codefirst and sql server express 2012.

I have enabled migrations and now do this in my Configuration.Seed method: (note that I want to set the primary key to 8 even though this is the first record in the database).

context.ProductCategoryDtoes.AddOrUpdate(x => x.Id,
    new ProductCategoryDto() { Id = 8, Name = "category1" }
);

My Model object is defined like this:

[Table("ProductCategory")]
public class ProductCategoryDto {
    public long Id { get; set; }
    public string Name { get; set; }
}

This results in a table in (SQL SERVER EXPRESS 2012) where the Id column has Identity = true, Identity seed = 1, identity increment = 1.

Now when I run migrations by doing an PM> Update-Database this result in a row with Id = 1.

So my question are:

1) How can I control the values of auto incremented primary keys when seeding data.

2) If the solution is to increment the key columns seed value, then how is this to be done when I am using Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());. This will nuke and rebuild the database everytime I update the database, so how would the seed value be updated in the fresh database?

Upvotes: 6

Views: 5070

Answers (4)

Nate Bolam
Nate Bolam

Reputation: 499

It is very hackish, but I ran into a scenario where I had to do it due to some report having hard-coded PK values. Fixing the reports was beyond my scope of work.

Context.Database.ExecuteSqlCommand("SET IDENTITY_INSERT dbo.ProductCategoryDto ON " +
     "INSERT INTO dbo.ProductCategoryDto (Id, Name) VALUES (8, 'category1') " +
     "SET IDENTITY_INSERT dbo.ProductCategoryDto OFF");

Upvotes: 0

Sym Phys
Sym Phys

Reputation: 51

Just create dummy entities with default values, then add your real data and afterwards delete the dummies. Not the best way but I guess there is no other...

Upvotes: 2

Admir Tuzović
Admir Tuzović

Reputation: 11177

Have you tried adding this on top of your Id property:

[DatabaseGenerated(DatabaseGeneratedOption.None)]
public long Id { get; set; }

Upvotes: 1

Spevy
Spevy

Reputation: 1325

It seems you are trying to defeat the purpose of an identity column. If you want to do this your only choice is to use SQL Commands Set IDENTITY_INSERT to allow you to insert the value and then run DBCC CHECKIDENT to update the seed. Not a really good idea. These options have security and performance limitations.

You may want to consider using a GUID instead. You can create GUIDs in code which are guaranteed to be unique, and you can also generate GUIDs in SQL as a column default.

With GUIDs, which are non sequential you will need to think through a good indexing strategy. This approach is also debatable.

Ultimately, it looks like you need a different strategy other than using an Identity Column.

Upvotes: 0

Related Questions