获取ValidationAttribute类型导致DbEntityValidationException

时间:2016-02-12 14:03:38

标签: c# entity-framework data-annotations

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

我需要知道的是ValidationAttribute确切地导致了验证错误。的即。我需要知道Type ValidationAttribute导致我的计划中出现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注释是否触发了验证错误?

2 个答案:

答案 0 :(得分:1)

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

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

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

更新

嗯,使用ValidationAttribute获取ErrorMessage的通用解决方案可以这样做:

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;
} 

答案 1 :(得分:0)

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

  

IValidatableObject是一个存在于System.ComponentModel.DataAnnotations中的接口。虽然它不是Entity Framework API的一部分,但您仍可以将其用于Entity Framework类中的服务器端验证。 IValidatableObject提供Entity Framework将在SaveChanges期间调用的Validate方法,或者您可以在任何时候想要验证类时自行调用。
  诸如Required和MaxLength之类的配置在单个字段上执行验证。在Validate方法中,您可以拥有更复杂的逻辑,例如,比较两个字段。

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