我如何可以使用自定义的验证在DB实体儿童模特属性

我如何可以使用自定义的验证在DB实体儿童模特属性

本文介绍了我如何可以使用自定义的验证在DB实体儿童模特属性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要:

我要一个数据注释验证器来引用同一类的另一个属性( TitleAuthorAndPublishingConfiguration )。

不过,DB.SaveChanges()不被直接调用这个类。相反,它被调用这个类的父( WebsiteConfiguration )。

所以 validationContext.ObjectType 将返回 WebsiteConfiguration ,我无法参照 TitleAuthorAndPublishingConfiguration 数据注释验证器内。


WebsiteConfiguration.cs

 公共类WebsiteConfiguration
{
    [键]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)
    公众诠释ID {搞定;组; }    公共TitleAuthorAndPublishingConfiguration TitleAuthorAndPublishing {搞定;组; }    公共BookChaptersAndSectionsConfiguration BookChaptersAndSections {搞定;组; }    公共SocialMediaLoginsConfiguration SocialMediaLogins {搞定;组; }    公共TagGroupsConfiguration TagGroups {搞定;组; }
}公共类TitleAuthorAndPublishingConfiguration
{
    公共字符串BOOKTITLE {搞定;组; }    公共BOOL |评论{搞定;组; }    //如何调用DB.SaveChanges()对父母,当我访问当前模型的属性?
    [RequiredIfOtherFieldIsEnabled(|评论)]
    公共字符串出版商{搞定;组; }
}// ...等子模型...

ApplicationDbContext.cs

  DbSet< WebsiteConfiguration> WebsiteConfiguration {获取;设置;}

示例更新code

 公共无效SeedWebsiteConfiguration()
    {
        VAR titleAuthorAndPublishingConfiguration =新TitleAuthorAndPublishingConfiguration()
        {
            //种子值
        };
        VAR bookChaptersAndSectionsConfiguration =新BookChaptersAndSectionsConfiguration()
        {
            //种子值
        };
        VAR socialMediaLoginConfiguration =新SocialMediaLoginsConfiguration()
        {
            //种子值
        };
        VAR tagGroupsConfiguration =新TagGroupsConfiguration()
        {
            //种子值
        };
        VAR websiteConfiguration =新WebsiteConfiguration()
        {
            TitleAuthorAndPublishing = titleAuthorAndPublishingConfiguration,
            BookChaptersAndSections = bookChaptersAndSectionsConfiguration,
            SocialMediaLogins = socialMediaLoginConfiguration,
            TagGroups = tagGroupsConfiguration
        };
        DB.WebsiteConfiguration.Add(websiteConfiguration);
        DB.SaveChanges();
    }


验证code

 公共类RequiredIfOtherFieldIsEnabledAttribute:ValidationAttribute
{
    私人字符串_ifWhatIsEnabled {搞定;组; }
    公共RequiredIfOtherFieldIsEnabledAttribute(字符串IfWhatIsEnabled)
    {
        _ifWhatIsEnabled = IfWhatIsEnabled;
    }    保护覆盖的ValidationResult的IsValid(对象currentPropertyValue,ValidationContext validationContext)
    {
        VAR isEnabledProperty = validationContext.ObjectType.GetProperty(_ifWhatIsEnabled);
        如果(isEnabledProperty == NULL)
        {
            返回新的ValidationResult(
                的String.Format(未知的属性:{0},_ifWhatIsEnabled)
            );
        }
        VAR isEnabledPropertyValue =(布尔)isEnabledProperty.GetValue(validationContext.ObjectInstance,NULL);        如果(isEnabledPropertyValue ==真)
        {
            如果(String.IsNullOrEmpty(currentPropertyValue.ToString()))
            {
                返回新的ValidationResult(的String.Format(,isEnabledProperty)这个字段,如果{0}启用必需);
            }
        }
        返回ValidationResult.Success;
    }
}


问题


  1. 有没有办法,我从 validationContext

  2. 访问儿童模特属性
  3. 我在我的做法误导?有没有更好的方式来多个模型存储为一个单一的数据库表中的大模型的一部分​​?


我希望不要有多个配置表和调用数据库。 (有在本实施例4子模型,但有可能是10+在下一应用程序。)

上面的设置是否满足在很多方面我的需要。但我不想放弃DataAnnotations的功能上的子模型!


奖金问题

我也碰到过几个帖子像这样的:
How我可以告诉数据注释验证器也验证复杂的子属性?

但是,这是4岁了,如果过什么改变了我不知道。

难道我试图做一些事情,基本上是不可能的(或至少是非常困难的)?


解决方案

No, there is a very simple solution that integrates perfectly with the framework and technologies using DataAnnotations.

You can create a custom ValidationAttribute that is called by EF Validation and call Validator.TryValidateObject inside. This way, when CustomValidation.IsValid is called by EF you launch child complex object validation by hand and so on for the whole object graph. As a bonus, you can gather all errors thanks to CompositeValidationResult.

i.e.

using System;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;

public class Program
{
    public static void Main() {
   var person = new Person {
      Address = new Address {
         City = "SmallVille",
         State = "TX",
         Zip = new ZipCode()
      },
      Name = "Kent"
   };

   var context = new ValidationContext(person, null, null);
   var results = new List<ValidationResult>();

   Validator.TryValidateObject(person, context, results, true);

   PrintResults(results, 0);

   Console.ReadKey();
}

private static void PrintResults(IEnumerable<ValidationResult> results, Int32 indentationLevel) {
   foreach (var validationResult in results) {
      Console.WriteLine(validationResult.ErrorMessage);
      Console.WriteLine();

      if (validationResult is CompositeValidationResult) {
         PrintResults(((CompositeValidationResult)validationResult).Results, indentationLevel + 1);
      }
   }
}

}

public class ValidateObjectAttribute: ValidationAttribute {
   protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
      var results = new List<ValidationResult>();
      var context = new ValidationContext(value, null, null);

      Validator.TryValidateObject(value, context, results, true);

      if (results.Count != 0) {
         var compositeResults = new CompositeValidationResult(String.Format("Validation for {0} failed!", validationContext.DisplayName));
         results.ForEach(compositeResults.AddResult);

         return compositeResults;
      }

      return ValidationResult.Success;
   }
}

public class CompositeValidationResult: ValidationResult {
   private readonly List<ValidationResult> _results = new List<ValidationResult>();

   public IEnumerable<ValidationResult> Results {
      get {
         return _results;
      }
   }

   public CompositeValidationResult(string errorMessage) : base(errorMessage) {}
   public CompositeValidationResult(string errorMessage, IEnumerable<string> memberNames) : base(errorMessage, memberNames) {}
   protected CompositeValidationResult(ValidationResult validationResult) : base(validationResult) {}

   public void AddResult(ValidationResult validationResult) {
      _results.Add(validationResult);
   }
}

public class Person {
  [Required]
  public String Name { get; set; }

  [Required, ValidateObject]
  public Address Address { get; set; }
}

public class Address {
  [Required]
  public String Street1 { get; set; }

  public String Street2 { get; set; }

  [Required]
  public String City { get; set; }

  [Required]
  public String State { get; set; }

  [Required, ValidateObject]
  public ZipCode Zip { get; set; }
}

public class ZipCode {
  [Required]
  public String PrimaryCode { get; set; }

  public String SubCode { get; set; }
}

这篇关于我如何可以使用自定义的验证在DB实体儿童模特属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 03:16