.NET 5+EF 5调用Pokemon API保存数据时遇标识列插入错误
解决EF 5.0中IDENTITY_INSERT关闭时无法插入身份列的问题
问题根源
这个错误的核心是:你向PokemonDtos表插入数据时,手动给标识列(通常是Id字段)赋值了,但SQL Server默认禁止显式插入标识列的值,除非开启IDENTITY_INSERT。而你通过json2csharp生成的实体类,大概率直接把Pokemon API返回的ID映射到了实体的标识字段上,导致EF尝试插入这个外部ID值。
解决方案
1. 修正实体类的标识列配置
确保EF识别出PokemonDto的标识列是数据库自动生成的,有两种配置方式:
- 数据注解方式:在标识列属性上添加注解
public class PokemonDto { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } // 新增字段存储API返回的Pokemon ID public int PokemonApiId { get; set; } // 其他属性... } - Fluent API方式:在DbContext的
OnModelCreating方法中配置protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<PokemonDto>() .Property(p => p.Id) .ValueGeneratedOnAdd(); }
2. 避免给标识列赋值
从Pokemon API获取数据后,不要将API返回的ID赋值给实体的Id字段,而是存入新增的专属字段(比如PokemonApiId),让数据库自动生成实体的标识ID:
var pokemonFromApi = await _httpClient.GetFromJsonAsync<PokemonApiResponse>("api/pokemon/1"); var pokemonDto = new PokemonDto { PokemonApiId = pokemonFromApi.Id, Name = pokemonFromApi.Name, // 其他属性赋值... // 不要给Id字段赋值 }; _context.PokemonDtos.Add(pokemonDto); await _context.SaveChangesAsync();
3. (不推荐)临时开启IDENTITY_INSERT
如果确实需要手动插入标识列值,可以临时开启该设置,但这会破坏数据库自动标识的逻辑,仅作为特殊场景的备选:
await _context.Database.ExecuteSqlRawAsync("SET IDENTITY_INSERT PokemonDtos ON"); _context.PokemonDtos.Add(pokemonDto); await _context.SaveChangesAsync(); await _context.Database.ExecuteSqlRawAsync("SET IDENTITY_INSERT PokemonDtos OFF");
4. 重新同步数据库配置
修改实体配置后,重新生成迁移并更新数据库,确保配置生效:
dotnet ef migrations add FixIdentityColumnConfig dotnet ef database update
内容的提问来源于stack exchange,提问作者Pablo Costa
相关产品推荐
相关产品推荐

