EF Core中如何禁止非空实体属性使用对应数据类型的默认值?
核心原因说明
[Required]特性仅控制字段不允许为NULL,值类型decimal的默认值0属于合法的非空值,因此不会被拦截。你需要通过添加校验规则禁止传入默认值,以下是针对PostgreSQL + EF Core的可行方案:
方案1:使用数据注解(推荐,自动适配多数据库)
在实体属性上添加[Range]特性,指定值的允许范围:
public class ExampleEntity { [Required] // 允许大于0的decimal值,若业务允许负数仅禁止0,可换成自定义校验或者方案2 [Range(typeof(decimal), "0.0000000001", "79228162514264337593543950335", ErrorMessage = "Amount不能为0")] public decimal Amount { get; set; } }
EF Core生成迁移时会自动创建对应的CHECK约束,PostgreSQL侧最终生成的字段规则会包含CHECK (Amount > 0),无论是通过EF写入还是直接操作数据库,都无法插入0值。
方案2:使用Fluent API直接配置数据库CHECK约束
如果不希望在实体类上加特性,可以在DbContext的OnModelCreating方法中手动配置约束,规则更灵活:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ExampleEntity>() .Property(e => e.Amount) // 约束名建议按规范命名,规则可自定义:如果仅禁止0就写 "Amount <> 0" .HasCheckConstraint("CK_ExampleEntity_Amount_NotZero", "Amount > 0"); }
两种方案配置完成后,新增EF迁移并更新到PostgreSQL数据库即可生效。
注意:如果表中已有旧数据存在Amount为0的情况,需要先清理不符合规则的旧数据,否则迁移执行时会报错。
如果需要在代码层提前校验错误,不需要等到数据库抛出约束异常,可以在DTO层添加同样的Range校验,在请求进入业务逻辑时就完成校验。
内容的提问来源于stack exchange,提问作者Vladyslav Kalashnikov
相关产品推荐
相关产品推荐

