Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework Code First AddOrUpdate method insert Duplicate values

I have simple entity:

public class Hall {     [Key]     public int Id {get; set;}      public string Name [get; set;} } 

Then in the Seed method I use AddOrUpdate to populate table:

var hall1 = new Hall { Name = "French" }; var hall2 = new Hall { Name = "German" }; var hall3 = new Hall { Name = "Japanese" };  context.Halls.AddOrUpdate(     h => h.Name,     hall1,     hall2,     hall3 ); 

Then I run in the Package Management Console:

Add-Migration Current Update-Database 

It's all fine: I have three rows in the table "Hall". But if I run in the Package Management Console Update-Database again I have already five rows:

Id  Name 1   French 2   Japaneese 3   German 4   French 5   Japanese 

Why? I think it is should be three rows again, not five. I tried to use Id property instead of Name but it does not make the difference.

UPDATE:

This code produces the same result:

var hall1 = new Hall { Id = 1, Name = "French" }; var hall2 = new Hall { Id = 2, Name = "German" }; var hall3 = new Hall { Id = 3, Name = "Japanese" };  context.Halls.AddOrUpdate(                 h => h.Id,                 hall1);  context.Halls.AddOrUpdate(                 h => h.Id,                 hall2);  context.Halls.AddOrUpdate(                 h => h.Id,                 hall3); 

Also I have the latest EntityFramework installed via nuget.

like image 325
Y.Yanavichus Avatar asked Apr 04 '12 08:04

Y.Yanavichus


2 Answers

Ok I was banging my face off the keyboard for an hour with this. If your table's Id field is an Identity field then it won't work so use a different one for identifierExpression. I used the Name property and also removed the Id field from the new Hall {...} initializer.

This tweak to the OPs code worked for me so I hope it helps someone:

protected override void Seed(HallContext context) {     context.Halls.AddOrUpdate(         h => h.Name,   // Use Name (or some other unique field) instead of Id         new Hall         {             Name = "Hall 1"         },         new Hall         {             Name = "Hall 2"         });      context.SaveChanges(); } 
like image 199
Ciarán Bruen Avatar answered Oct 03 '22 00:10

Ciarán Bruen


I know this is an old question, but the right answer is that if you are setting the id # yourself and you want to use AddOrUpdate then you need to tell EF/SQL that you don't want it to generate the ID #.

modelBuilder.Entity<MyClass>().Property(p => p.Id)     .HasDatabaseGeneratedOption(System.ComponentModel     .DataAnnotations.Schema.DatabaseGeneratedOption.None);  

The down side to this is that when you insert a new item you need to set it's Id, so if this is done dynamically at runtime (instead of from seed data) then you will need to calculate out the next Id. Context.MyClasses.Max(c=>c.Id) + 1 works well.

like image 36
Anthony Nichols Avatar answered Oct 03 '22 00:10

Anthony Nichols