使用Entity Framework向含外键的表插入数据失败求助
解决EF插入关联实体时重复插入的问题
问题原因
你赋值的Developer、Publisher等关联对象,没有被当前DbContext跟踪(可能是从外部传入、或来自另一个上下文实例),EF会将它们判定为新实体,从而执行不必要的插入操作。而Developers表的Id是自增列,插入时显式指定Id但未开启IDENTITY_INSERT,因此抛出报错。
解决方案
方案1:将已存在的关联实体附加到当前上下文
如果确定这些实体已经存在于数据库中,使用Attach方法让上下文跟踪它们,并标记为未修改状态,EF就不会尝试插入它们:
// 在SaveChanges之前执行 context.Attach(game.Developer); context.Attach(game.Publisher); foreach (var platform in game.Platforms) { context.Attach(platform); } foreach (var genre in game.Genres) { context.Attach(genre); } context.Add(game); await context.SaveChangesAsync();
方案2:显式使用外键属性(推荐)
在Game模型中添加对应的外键字段,直接赋值外键ID而非导航属性,这样EF只会处理Games表及多对多中间表,不会操作关联实体表:
// 修改Game模型,添加外键属性 public class Game { [Key] public int Id { get; set; } // ...其他原有属性 // 添加外键字段 public int DeveloperId { get; set; } public Developer Developer { get; set; } public int PublisherId { get; set; } public Publisher Publisher { get; set; } public List<Platform> Platforms { get; set; } public List<Genre> Genres { get; set; } // ...其他方法 } // 赋值时直接用ID game.DeveloperId = Developer.Id; game.PublisherId = Publisher.Id; game.Platforms = SelectedPlatforms; // 同样需要确保这些平台被上下文跟踪,或用方案1的Attach处理 game.Genres = SelectedGenres;
方案3:从当前上下文获取关联实体
如果能拿到关联实体的ID,直接通过当前DbContext的Find或查询方法获取实体,这样上下文会自动跟踪这些实体,不会重复插入:
// 假设你有对应的ID变量 game.Developer = await context.Developers.FindAsync(selectedDeveloperId); game.Publisher = await context.Publishers.FindAsync(selectedPublisherId); game.Platforms = await context.Platforms .Where(p => selectedPlatformIds.Contains(p.Id)) .ToListAsync(); game.Genres = await context.Genres .Where(g => selectedGenreIds.Contains(g.Id)) .ToListAsync(); context.Add(game); await context.SaveChangesAsync();
内容的提问来源于stack exchange,提问作者Desmond Mayer
相关产品推荐
相关产品推荐

