EF Core:添加DatabaseGenerated后Id是否为主键?如何定义自动生成主键?
场景说明
我创建了名为Student的实体,代码如下:
public class Student { [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public string Name { get; set; } }
当为Id属性添加Required特性后,必须手动输入Id的值。我希望通过EF Core实现Id属性的自动生成与自增,示例代码如下:
static void Main(string[] args) { var db = new AppDbContext(); db.Add(new Student { Name = "Peter" }); db.SaveChanges(); }
问题
- 添加
DatabaseGenerated特性后,Id是否会成为主键? - 如何定义一个可自动生成、无需手动设置值的主键?
问题1解答
不会。[DatabaseGenerated(DatabaseGeneratedOption.Identity)]仅负责指定该列的值由数据库自动生成,它本身不会自动将属性设为主键。EF Core的主键识别依赖命名约定:默认会把命名为Id或者[实体名]Id的属性认作主键,这和DatabaseGenerated特性无关。如果属性不遵循这个命名规则,就算加了该特性,也不会自动成为主键。
问题2解答
要实现自动生成、无需手动赋值的主键,分两种场景处理:
场景1:遵循EF Core默认命名约定
如果主键属性命名为Id或StudentId(对应实体Student),EF Core会自动将其设为主键。对于int类型的主键,EF Core默认就会配置成数据库自增列,甚至可以不用加DatabaseGenerated特性:
public class Student { // 不加DatabaseGenerated特性也可,EF Core默认把int类型的Id设为自增主键 public int Id { get; set; } public string Name { get; set; } }
这种情况下,执行db.Add(new Student { Name = "Peter" });时无需给Id赋值,SaveChanges()时数据库会自动生成自增值。
场景2:不遵循默认命名约定
如果主键属性不是Id或[实体名]Id(比如叫StudentNumber),需要手动标记主键并配置自动生成:
public class Student { [Key] // 显式标记为主键 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int StudentNumber { get; set; } public string Name { get; set; } }
也可以用Fluent API在DbContext的OnModelCreating方法中配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Student>() .HasKey(s => s.StudentNumber) // 指定主键 .Property(s => s.StudentNumber) .ValueGeneratedOnAdd(); // 配置为添加时自动生成值 }
另外注意:不要给自动生成的主键加[Required]特性,这个特性会让EF Core判定你必须手动赋值,反而会出现你遇到的需要手动输入Id的问题。
内容的提问来源于stack exchange,提问作者MB_18

