代码之家  ›  专栏  ›  技术社区  ›  kovac

EF核心不提升validationexception

  •  2
  • kovac  · 技术社区  · 6 年前

    我有一个基地 DbContext 类类

    public abstract class DbContextBase : DbContext
    {
        public DbContextBase()
        {
        }
    
        public DbContextBase(DbContextOptions options)
            : base(options)
        {
        }
    
        public override int SaveChanges()
        {
            this.ValidateEntities();
    
            return base.SaveChanges();
        }
    
        public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            this.ValidateEntities();
    
            return base.SaveChangesAsync(cancellationToken);
        }
    
         public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
         {
            this.ValidateEntities();
    
            return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
        }
    
        protected virtual void ValidateEntities()
        {
            var entities = this.ChangeTracker.Entries().
                                Where(s => s.State == EntityState.Added || s.State == EntityState.Modified);
    
            foreach (var entity in entities)
            {
                var validationContext = new ValidationContext(entity);
                Validator.ValidateObject(entity, validationContext);
            }
        }
    }
    

    我的所有数据库上下文类都继承自这个基类。问题是这条线 Validator.ValidateObject() 不是投掷 ValidationException 即使存在验证冲突。在调试器中,我可以看到这行被执行。例如,对于下面的模型类,我尝试调用 SaveChangesAsync() 具有 Name 设置为 null 但是验证通过了:

    public class MyModel : IEntity<long>
    {
        [Key]
        public long Id { get; set; }
    
        [Required]
        public string Name { get; set; }
    }
    

    IEntity<T> 只是强加财产 Id 在所有模型上。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Ivan Stoev    6 年前

    问题是变量 entity 不保留实体实例,但更改跟踪器( EntityEntry )实例,因此代码试图验证错误的内容。

    因此,要么重命名变量,然后使用 entry.Entity 财产:

    var entries = this.ChangeTracker.Entries()
        .Where(s => s.State == EntityState.Added || s.State == EntityState.Modified);
    
    foreach (var entry in entries)
    {
        var validationContext = new ValidationContext(entry.Entity);
        Validator.ValidateObject(entry.Entity, validationContext);
    }
    

    或者保持代码不变,但要确保 entities 变量持有可枚举的实体实例:

    var entities = this.ChangeTracker.Entries()
        .Where(s => s.State == EntityState.Added || s.State == EntityState.Modified)
        .Select(s => s.Entity); // <--
    
        2
  •  0
  •   Mohamed Elrashid    6 年前

    代码

    public class MyModel : IEntity<long>
    {
        [Key]
        public long Id { get; set; }
    
        [Required(AllowEmptyStrings = false)]
        public string Name { get; set; }
    }
    

    更多