获取导致 DbEntityValidationException 的 ValidationAttribute 类型

Get Type of ValidationAttribute causing a DbEntityValidationException

我正在使用依赖于 System.ComponentModel.DataAnnotations.ValidationAttribute 的 Entity Framework 的验证。因此,当我调用 DbContext.SaveChanges() 并且实体 属性 验证失败时,将抛出 DbEntityValidationException

我需要知道的是 ValidationAttribute 究竟是哪个 ValidationAttribute 导致了验证错误。 即我需要知道 ValidationAttributeType 在我的程序中导致 DbEntityValidationException

我已经知道如何遍历 DbEntityValidationException 中的验证错误集合。但是那里没有所需的信息。


例子

假设我有一个简单的模型,其中有一个 属性,它有两个数据注释...

class Model
{
    [Required]
    [MaxLength(3)]
    string Code { ... }
}

...并想像这样添加一个新实例:

try
{
    var model = new Model { Code = "ThisIsTooLong" };
    dbContext.Set<Model>().Add(model);
    dbContext.SaveChanges();
}
catch (DbEntityValidationException e)
{
    Type unsatisfiedValidationAttribute = MagicFunction();
}

在上面的例子中抛出了一个 DbEntityValidationException 并且变量 unsatisfiedValidationAttribute 应该等于 typeof(MaxLengthAttribute).

MagicFunction() 必须做什么才能知道 RequiredMaxLength 注释是否触发了验证错误?

我想你要找的是Validator.TryValidateObject静态方法:

var modelToSave = new Model { Code = "ThisIsTooLong" };
var results = new List<ValidationResult>();
bool isValid=Validator.TryValidateObject( modelToSave, context, results, true);

如果您的实体无效,您将在 results 列表中保留每个失败的验证。

更新

好吧,使用 ErrorMessage 获取 ValidationAttribute 的通用解决方案可能是这样做的:

public static ValidationAttribute GetAttribute(Type entityType, string property, string errorMessage)
{
   var attributes = typeof(entityType)
                   .GetProperty(property)
                   .GetCustomAttributes(false)
                   .OfType<ValidationAttribute>()
                   .ToArray();
   var attribute= attributes.FirstOrDefault(a => a.ErrorMessage == errorMessage);
   return attribute;
} 

如果您使用的是 Entity Framework 4.1+,这可能对您有所帮助。您可以在您的实体中实施您自己的验证逻辑,并且 return 您自己的错误代码用于不同的验证问题。

IValidatableObject is an interface that lives in System.ComponentModel.DataAnnotations. While it is not part of the Entity Framework API, you can still leverage it for server-side validation in your Entity Framework classes. IValidatableObject provides a Validate method that Entity Framework will call during SaveChanges or you can call yourself any time you want to validate the classes.
Configurations such as Required and MaxLength perform validaton on a single field. In the Validate method you can have even more complex logic, for example, comparing two fields.

public class Blog : IValidatableObject
    {
        public int Id { get; set; }
        [Required]
        public string Title { get; set; }
        public string BloggerName { get; set; }
        public DateTime DateCreated { get; set; }
        public virtual ICollection<Post> Posts { get; set; }

        public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
        {
            if (Title == BloggerName)
            {
                yield return new ValidationResult
                 ("Blog Title cannot match Blogger Name", new[] { "Title", “BloggerName” });
            }
        }
    }

Entity Framework Validation