如何根据实体框架中的上下文验证实体?

问题描述 投票:1回答:1

我通常通过调用entity.IsValid()并为实体创建适当的ValidationAttribute类来验证Entity Framework中的实体。

然而,现在我遇到一个案例,当我需要验证一个实体时,不仅仅是它自己,而是在它所属的上下文中,作为一个例子:

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class CourseValidation : ValidationAttribute
{
    public CourseValidation() {}
    protected override ValidationResult IsValid (object value, ValidationContext validationContext)
    {
        List<string> messages = new List<string>();
        if (value is Course)
        {
            Course course = (Course)value;
            if (course.Context != null)
            {
                if (course.Context.Courses.Any(c => c.Name == course.Name && c.Department.ID == course.Department.ID))
                {
                    messages.Add($"Cannot create a course with name {course.Name} in {course.Department.Name} department because a course with this name already exists in this department.");
                }
            }
            else messages.Add("Course is being improperly handled by the software, please contact support department");
         }
         else messages.Add("Course is expected, but does not exist");

         if (messages.Count > 0) return new ValidationResult(string.Join(Environment.NewLine, messages));
         else return ValidationResult.Success;
     }
}

有一个困难:简单地使用context.Courses.Add(course)不会导致context.Courses.Where(c => c.Name == course.Name)返回任何东西。相反,在实体作为整个集合的一部分可用之前,它将需要context.SaveChanges()。这意味着在尝试将实体保存到数据库之前,我将无法针对集合验证实体。

我知道这个例子很简单,并且可以通过数据库端唯一约束来处理,但即使我们不打算查看更复杂的示例,我也看到了一个很好的理由在尝试将无效条目提交到数据库(因为如果事务中的一个条目冒犯了约束,整个事务将被阻止),并将所有验证标准放在一个地方,而不是在不同的类和/或数据库模式之间拆分(以保持单一责任) 。

在哪些方面可以实施验证策略以满足这些要求?

c# .net entity-framework validation
1个回答
1
投票

我们所做的是覆盖上下文的ValidateEntity method。这使您有机会在提交更改之前检查数据库中的内容(如重复项等)。

只需将overriden类添加到您的上下文并执行您需要的任何检查:

protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry,
    IDictionary<object, object> items)
{

    if (entityEntry.Entity is Course &&
                (entityEntry.State == EntityState.Added 
                  || entityEntry.State == EntityState.Modified))
    {
        var courseToCheck = ((Course)entityEntry.Entity);

        //check for uniqueness 
        if (Courses.Any(c => c.Name == course.Name && c.Department.ID == course.Department.ID)))
            return 
                   new DbEntityValidationResult(entityEntry,
                 new List<DbValidationError>
                     {
                         new DbValidationError( "Name",
                             $"Cannot create a course with name {courseToCheck .Name} in {courseToCheck .Department.Name} department because a course with this name already exists in this department.")
                     });
    }

    return base.ValidateEntity(entityEntry, items);
}

现在你可以在保存之前调用context.GetValidationErrors()并处理错误。例如here

© www.soinside.com 2019 - 2024. All rights reserved.