EF核心未引发ValidationException

时间:2019-01-06 02:40:55

标签: c# asp.net-core-webapi ef-core-2.1 model-validation

我有一个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);
        }
    }
}

我所有的Db Context类都继承自该基类。问题是即使存在验证冲突,行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 个答案:

答案 0 :(得分:3)

问题在于变量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); // <--

答案 1 :(得分:0)

代码

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

    [Required(AllowEmptyStrings = false)]
    public string Name { get; set; }
}

更多