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.
Solution 1:
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();
}
Solution 2:
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.
Solution 3:
This code works:
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(HallContext context)
{
context.Halls.AddOrUpdate(
h => h.Id,
new Hall
{
Id = 1,
Name = "Hall 1"
},
new Hall
{
Id = 2,
Name = "Hall 2"
});
context.SaveChanges();
}