2015-11-03 6 views
12

सारांश:मैं डीबी इकाई के बाल मॉडल पर कस्टम सत्यापन गुणों का उपयोग कैसे कर सकता हूं?

मैं एक ही कक्षा (TitleAuthorAndPublishingConfiguration) में एक और संपत्ति को संदर्भित करने के एक डेटा एनोटेशन सत्यापनकर्ता चाहते हैं।

हालांकि, इस वर्ग पर डीबी। सेव चेंज() को सीधे नहीं कहा जा रहा है। इसके बजाय इसे इस वर्ग के माता-पिता (WebsiteConfiguration) पर बुलाया जा रहा है।

इसलिए validationContext.ObjectTypeWebsiteConfiguration लौटा रहा है और मैं डेटा एनोटेशन सत्यापनकर्ता के भीतर TitleAuthorAndPublishingConfiguration के गुणों को संदर्भित करने में असमर्थ हूं।


WebsiteConfiguration.cs

public class WebsiteConfiguration 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int ID { get; set; } 

    public TitleAuthorAndPublishingConfiguration TitleAuthorAndPublishing { get; set; } 

    public BookChaptersAndSectionsConfiguration BookChaptersAndSections { get; set; } 

    public SocialMediaLoginsConfiguration SocialMediaLogins { get; set; } 

    public TagGroupsConfiguration TagGroups { get; set; } 
} 

public class TitleAuthorAndPublishingConfiguration 
{ 
    public string BookTitle { get; set; } 

    public bool IsPublished { get; set; } 

    // how do I access a property of current model when calling DB.SaveChanges() on parent? 
    [RequiredIfOtherFieldIsEnabled("IsPublished")] 
    public string Publisher { get; set; } 
} 

// ... and other sub models... 

ApplicationDbContext.cs

DbSet<WebsiteConfiguration> WebsiteConfiguration {get;set;} 

उदाहरण अद्यतन कोड

public void SeedWebsiteConfiguration() 
    { 
     var titleAuthorAndPublishingConfiguration = new TitleAuthorAndPublishingConfiguration() 
     { 
      // seed values 
     }; 
     var bookChaptersAndSectionsConfiguration = new BookChaptersAndSectionsConfiguration() 
     { 
      // seed values 
     }; 
     var socialMediaLoginConfiguration = new SocialMediaLoginsConfiguration() 
     { 
      // seed values 
     }; 
     var tagGroupsConfiguration = new TagGroupsConfiguration() 
     { 
      // seed values 
     }; 
     var websiteConfiguration = new WebsiteConfiguration() 
     { 
      TitleAuthorAndPublishing = titleAuthorAndPublishingConfiguration, 
      BookChaptersAndSections = bookChaptersAndSectionsConfiguration, 
      SocialMediaLogins = socialMediaLoginConfiguration, 
      TagGroups = tagGroupsConfiguration 
     }; 
     DB.WebsiteConfiguration.Add(websiteConfiguration); 
     DB.SaveChanges(); 
    } 

सत्यापनकर्ता कोड

public class RequiredIfOtherFieldIsEnabledAttribute : ValidationAttribute 
{ 
    private string _ifWhatIsEnabled { get; set; } 


    public RequiredIfOtherFieldIsEnabledAttribute(string IfWhatIsEnabled) 
    { 
     _ifWhatIsEnabled = IfWhatIsEnabled; 
    } 

    protected override ValidationResult IsValid(object currentPropertyValue, ValidationContext validationContext) 
    { 
     var isEnabledProperty = validationContext.ObjectType.GetProperty(_ifWhatIsEnabled); 
     if (isEnabledProperty == null) 
     { 
      return new ValidationResult(
       string.Format("Unknown property: {0}", _ifWhatIsEnabled) 
      ); 
     } 
     var isEnabledPropertyValue = (bool)isEnabledProperty.GetValue(validationContext.ObjectInstance, null); 

     if (isEnabledPropertyValue == true) 
     { 
      if (String.IsNullOrEmpty(currentPropertyValue.ToString())) 
      { 
       return new ValidationResult(String.Format("This field is required if {0} is enabled", isEnabledProperty)); 
      } 
     } 
     return ValidationResult.Success; 
    } 
} 

प्रश्न

  1. वहाँ मुझे validationContext से बच्चे मॉडल गुण का उपयोग करने के लिए एक तरीका है?

  2. क्या मैं अपने दृष्टिकोण में गुमराह हूं? क्या एक डीबी टेबल में बड़े मॉडल के हिस्से के रूप में कई मॉडलों को स्टोर करने का कोई बेहतर तरीका है?

मैं उम्मीद कर रहा था कि एकाधिक कॉन्फ़िगरेशन टेबल न हो और डीबी को कॉल न करें। (इस उदाहरण में 4 बच्चे मॉडल हैं, लेकिन अगले ऐप में 10+ हो सकते हैं।)

उपरोक्त सेटअप मेरी आवश्यकताओं को कई तरीकों से पूरा करता है। लेकिन मैं उप मॉडल पर DataAnnotations की कार्यक्षमता को छोड़ना नहीं चाहता!


बोनस प्रश्न

मैं इस तरह कुछ पोस्ट में आ गए हैं: How can I tell the Data Annotations validator to also validate complex child properties?

लेकिन वह 4 साल पुरानी है, और अगर कुछ भी तब से बदल गया है मैं सोच रहा हूँ ।

क्या मैं कुछ ऐसा करने की कोशिश कर रहा हूं जो मूल रूप से असंभव है (या कम से कम बहुत मुश्किल)?

+0

'मैं कैसे वर्तमान मॉडल की एक संपत्ति जब माता-पिता पर DB.SaveChanges() कॉल उपयोग करते हैं?' मैं समझने के लिए तुम क्या मतलब है संघर्ष कर रहा हूँ ... आप का उपयोग करने के लिए इच्छुक रहे हैं प्रकाशक के वर्ग के सदस्यों की आवश्यकता है? और आप अपने डेटा एनोटेशन का उपयोग करके ऐसा करना चाहते हैं? मैं उलझन में हूं और समझना चाहता हूं। –

+0

मैं 'TitleAuthorAndPublishingConfiguration' की किसी अन्य प्रॉपर्टी को संदर्भित करने के लिए' TitleAuthorAndPublishingConfiguration' की संपत्ति पर एक डेटा एनोटेशन सत्यापनकर्ता चाहता हूं। लेकिन 'डीबी। सेव चेंज()' इस वर्ग पर सीधे नहीं बल्कि इसके माता-पिता - 'वेबसाइट कॉन्फ़िगरेशन' पर नहीं कहा जा रहा है। –

+0

मैंने प्रश्न को अद्यतन किया है, उम्मीद है कि इसे स्पष्ट बनाने के लिए –

उत्तर

2

Am मैं कुछ है कि मूल रूप से असंभव (या कम से कम बहुत मुश्किल है) करने का प्रयास कर?

नहीं, एक बहुत ही सरल समाधान है जो डेटाएनोटेशन का उपयोग करके ढांचे और प्रौद्योगिकियों के साथ पूरी तरह एकीकृत करता है।

आप एक कस्टम ValidationAttribute कि एफई मान्यता से पुकारा जाता है बना सकते हैं और Validator.TryValidateObject अंदर कॉल कर सकते हैं। इस तरह, जब CustomValidation.IsValid ईएफ द्वारा बुलाया जाता है तो आप पूरे ऑब्जेक्ट ग्राफ़ के लिए हाथ से बच्चे जटिल ऑब्जेक्ट सत्यापन लॉन्च करते हैं। बोनस के रूप में, आप CompositeValidationResult पर सभी त्रुटियों को धन्यवाद दे सकते हैं।

यानी

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

धन्यवाद। मैं इसे जाने दूंगा। –

संबंधित मुद्दे

 संबंधित मुद्दे