我有简单的实体:
public class Hall
{
[Key]
public int Id {get; set;}
public string Name [get; set;}
}
然后在Seed
的方法我用AddOrUpdate
填充表:
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
);
然后,我在包管理控制台运行:
Add-Migration Current
Update-Database
这是所有罚款:我有表中“霍尔”三行。 但是,如果我在包管理控制台运行Update-Database
再次我已经五行:
Id Name
1 French
2 Japaneese
3 German
4 French
5 Japanese
为什么? 我认为这是应该重新三人行,不是五个。 我试图用Id
属性,而不是Name
,但它不赚取差价。
更新:
此代码产生相同的结果:
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);
我也有通过的NuGet安装了最新的EntityFramework。
Answer 1:
好吧,我撞了我的脸离开键盘与此一个小时。 如果您的表的ID字段是一个标识字段,那么它不会工作,所以使用不同的一个identifierExpression。 我用的是Name属性,也从取出的Id场new Hall {...}
初始化。
这种调整对代码为我工作的有机磷农药,所以我希望它可以帮助别人:
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();
}
Answer 2:
此代码的工作:
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();
}
Answer 3:
我知道这是一个老问题,但正确的答案是,如果您自行设置编号和您要使用AddOrUpdate,那么你需要告诉你不希望它生成编号EF / SQL。
modelBuilder.Entity<MyClass>().Property(p => p.Id)
.HasDatabaseGeneratedOption(System.ComponentModel
.DataAnnotations.Schema.DatabaseGeneratedOption.None);
向下的一面的情况是,当你插入你需要设置一个新的项目的ID,因此,如果这是在运行时(而不是从种子数据)动态完成的,那么你将需要计算出下一个ID。 Context.MyClasses.Max(c=>c.Id) + 1
工作良好。
Answer 4:
如果你错误地设置了实体状态这也可以引起。 我一直得到以下错误,当我跑更新数据库...“序列包含一个以上的匹配元素。”
例如,我对每个更新的数据库命令(这当然是不应该播数据时发生的),然后下一更新数据库命令将不会在所有的,因为它找到一个以上的匹配工作正在创建重复的行(因此序列错误说我有一个以上的匹配行)。 那是因为我已经覆盖的SaveChanges在我的上下文文件,一个方法调用ApplyStateChanges ...
public override int SaveChanges()
{
this.ApplyStateChanges();
return base.SaveChanges();
}
我用ApplyStateChanges确保添加对象图时,实体框架知道对象明确是否在添加或修改状态。 关于我如何使用ApplyStateChanges整个的解释可以发现在这里 。
而这个伟大的工程(但需要注意的!)......如果你也使用播种迁移CodeFirst数据库,那么上面的方法会造成严重破坏的AddOrUpdate()种子的方法中调用。 所以任何事情之前,请查看您的DbContext文件,并确保你不是在路上覆盖的SaveChanges以上,否则你会最终得到重复数据运行更新的数据库命令第二次,然后在所有的都不行第三次,因为有一个为每个匹配项不止一行。
当它发生的时候,你并不需要配置AddOrUpdate()来击败容易和初始数据库播种的整个目的的Id ...。 它工作正常,通过这样的:
context.Students.AddOrUpdate(
p => p.StudentName,
new Student { StudentName = "Bill Peters" },
new Student { StudentName = "Jandra Nancy" },
new Student { StudentName = "Rowan Miller" },
new Student { StudentName = "James O'Dalley" },
只是,只要我不重写我的背景文件SaveChanges方法一起ApplyStateChanges通话。 希望这可以帮助。
Answer 5:
这为我工作
- 删除表中的所有行。
- 重置增量同一性为0
DBCC CHECKIDENT (yourtablename, RESEED, 0)
在指定的主键Seed()
必须使得它们不重复匹配在数据库中的表)。 - 在“种子”方法指定主密钥。
- 运行
Seed()
方法几次,你检查它们是否重复。
Answer 6:
我发现AddOrUpdate
工作正常与不ID的领域。 如果这对你的作品: context.Halls.AddOrUpdate(h => h.Name, hall1, hall2, hall3)
您可能需要使用霍尔的名字,如“French_test_abc_100”,“German_test_abc_100”等。
这将停止硬编码的测试数据弄乱的东西了,当你正在测试您的应用程序。
Answer 7:
如果对象(大厅)的ID为0,它是一种插入。 我认为你需要仔细检查id字段的厅内对象
Answer 8:
是您的ID字段标识字段? 我也陷入了同样的问题。 当我删除从我的ID字段中的身份地位,并设置标识进入数据库,即解决了问题。
这为我工作,因为这些是查找表,不应该是标识字段,反正。
Answer 9:
我认为这是可能的,你需要取消现有的数据库迁移(即从头开始你的数据库)的东西,如“更新,数据库TargetMigration:0”后跟“更新-数据库”。
正因为如此,你不会放弃现有的表或值,你只需要添加/更新这些值。 需要为了得到你想要的结果发生。
以下是EF迁移一个很好的参考: http://elegantcode.com/2012/04/12/entity-framework-migrations-tips/
Answer 10:
我使用的ID字段作为身份/ Key和添加属性不是由服务器分配的ID。 这解决了这个问题对我来说。
public class Hall
{
[Key]
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int Id {get; set;}
public string Name [get; set;}
}
Answer 11:
只是为了Ciaren的答案,重新上ModelCreating上下文下面的代码,帮我解决类似的问题。 确保变革“的ApplicationContext”你的DbContext的名字。
public class ApplicationContext : DbContext, IDbContext { public ApplicationContext() : base("ApplicationContext") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); Database.SetInitializer<ApplicationContext>(null); base.OnModelCreating(modelBuilder); } }
Answer 12:
我发现这个工作,身份位置应该是0,当种子首轮。 您可以使用重置:
DBCC CHECKIDENT (tableName, RESEED, 0)
Answer 13:
你可能也做到了这一点:
context.Halls.AddOrUpdate(new Hall[]{hall1,hall2, hall3});
文章来源: Entity Framework Code First AddOrUpdate method insert Duplicate values