2015-08-23 4 views
7

मैं एक कस्टम सत्यापन [IsUnique] बनाने की कोशिश कर रहा हूं। यह जांचें कि क्या संपत्ति मूल्य अद्वितीय है और एक उचित संदेश लौटाता है।सी # कस्टम सत्यापन अद्वितीय संपत्ति - जेनेरिक कक्षाएं

यह मेरा कोड है, लेकिन यह केवल एक निर्दिष्ट वर्ग के लिए काम करता है, मेटाडेटा द्वारा उचित कक्षा प्राप्त करने के लिए एक विधि करना संभव है?

public class ArticleMetaData 
    { 
     [Required(AllowEmptyStrings = false)] 
     [IsUnique("Name")] 
     public String Name{ get; set; }  
    } 

और अपने कस्टम मान्यता:

class IsUnique : ValidationAttribute 
    { 
     public IsUnique(string propertyNames) 
     { 
      this.PropertyNames = propertyNames; 
     } 

     public string PropertyNames { get; private set; } 

     protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
     { 

      var myproperty = validationContext.ObjectType.GetProperty(PropertyNames); 
      var value = propiedad.GetValue(validationContext.ObjectInstance, null); 

      IEnumerable<String> properties; 

      List<string> propertiesList = new List<string>(); 
      propertiesList.Add(myproperty.Name); 

      var dba = new myContext(); 

      if (dba.Articles.Any(article => article.Name == (string)value)) 
      { 
       return new ValidationResult("The name already exist", propertiesList); 
      } 
      return null; 
     } 
    } 

विचार बस एनोटेशन [isUnique] उपयोग करने के लिए हो सकता है और विधि टिप्पणी के साथ वर्ग लेते हैं और इसी इकाई खोज करते हैं।

+1

संभव डुप्लिकेट [मैं जेनरिक स्टोर कर सकते हैं एक वस्तु के क्षेत्र में विशेषता] (http://stackoverflow.com/questions/304640/can-i-store-the-generics-attribute -इंटर-ए-ऑब्जेक्ट-फ़ील्ड) –

+0

क्या आप उपयोगकर्ता को डेटाबेस में डुप्लीकेट रिकॉर्ड सहेजने से रोकने की कोशिश कर रहे हैं? –

+0

@ जुआनएम.इलोसेगुई मेरा लक्ष्य है। डुप्लिकेट नाम, ईमेल इत्यादि नहीं, यह एक अद्वितीय कुंजी एसक्यूएल – grteibo

उत्तर

4

प्रमाणीकरण गुण लिखते समय, आप प्रमाणीकरण के बारे में कुछ जानकारी प्राप्त करने के लिए प्रमाणीकरण कॉन्टेक्स्ट का उपयोग कर सकते हैं जैसे कि आप जिस संपत्ति का सत्यापन कर रहे हैं, उस वस्तु का प्रकार जिसे आप मान्य कर रहे हैं और इसी तरह।

इसलिए आपको यह घोषणा करने की आवश्यकता नहीं है कि आप किस संपत्ति को विशिष्टता के लिए जांचना चाहते हैं, या आपको कौन सी इकाई जांचनी चाहिए, या घटना आपको प्रतिबिंब का उपयोग करके मूल्य पुनर्प्राप्त करने की आवश्यकता नहीं है, क्योंकि मान IsValid विधि को पास कर दिया गया है ।

डीबीकॉन्टेक्स्ट का उपयोग करते समय, आप एसक्यूएल प्रश्नों का उपयोग कर सकते हैं, ताकि आप एसक्यूएल क्वेरी का उपयोग करके विशिष्टता की जांच कर सकें। फ्लाई पर जेनेरिक लिनक क्वेरी बनाने की कोशिश करने से यह अधिक सरल है।

यह विचार आपकी मदद कर सकता है। यहाँ विचार के अनुसार अपने कोड में कुछ बदलाव है:

protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
{ 
    var db = new YourDBContext(); 

    var className = validationContext.ObjectType.Name.Split('.').Last(); 
    var propertyName = validationContext.MemberName; 
    var parameterName = string.Format("@{0}", propertyName); 

    var result = db.Database.SqlQuery<int>(
     string.Format("SELECT COUNT(*) FROM {0} WHERE {1}={2}", className, propertyName, parameterName), 
     new System.Data.SqlClient.SqlParameter(parameterName, value)); 
    if (result.ToList()[0] > 0) 
    { 
     return new ValidationResult(string.Format("The '{0}' already exist", propertyName), 
        new List<string>() { propertyName }); 
    } 

    return null; 
} 

इस विशेषता का उपयोग करने के लिए बस अपनी संपत्ति ऊपर डाल [IsUnique]।

[IsUnique] 
YourProperty { get; set; } 

तो इस तरह के कोड का उपयोग कर एक परीक्षण चलाने:

var db = new YourDbContext(); 
db.Configuration.ValidateOnSaveEnabled = true; 
db.Categories.Add(new YourEntity() { YourProperty = "DuplicateName" }); 
db.SaveChanges(); 

यह गुण का उपयोग कर अपने संस्था की केवल इस तरह के पहलू को मान्य करने के लिए एक अच्छा अभ्यास है, कि ऑफलाइन वैध किया जा सकता है।

स्ट्रिंग लम्बाई, नियमित इंटरैक्शन, आवश्यक और ऐसे सत्यापन जैसे सत्यापन गुण अच्छे गुणों के उदाहरण हैं और सत्यापन गुण जो यूनिकनेस या अन्य डेटाबेस से संबंधित नियमों की जांच करते हैं, अनुचित गुणों के उदाहरण हैं।

+0

के रूप में होगा, मैं आपका उदाहरण लागू करने की कोशिश कर रहा हूं। आपके पिछले अनुच्छेद के बारे में मैं उससे सहमत हूं, लेकिन कुछ मामलों में सिस्टम को यह सत्यापित करना होगा कि उपयोगकर्ता नाम डुप्लिकेट नहीं करता है। सुझावों के लिए धन्यवाद! – grteibo

+0

@grteibo, आपका स्वागत है :) मामलों में सिस्टम को डुप्लिकेट डेटा को रोकना चाहिए, यह आपके व्यवसाय तर्क कोड में ऐसा करना बेहतर है। वहां आप डुप्लिकेट प्रविष्टि की जांच करने और उसका पुन: उपयोग करने के लिए जेनेरिक विधि बना सकते हैं। ऐसी विधि का सिंटैक्स हो सकता है: बूल IsUnique (स्ट्रिंग प्रॉपर्टीनाम, ऑब्जेक्ट वैल्यू, YourDbContext डीबी) –

+0

पहले मैंने व्यवसाय तर्क प्रणाली में प्रदर्शन मान्यताओं से संपर्क किया। लेकिन मैंने सोचा कि यह इकाइयों में एनोटेशन के माध्यम से किया जाएगा। – grteibo

1

मुझे लगता है कि डेटाबेस को इसके कार्यों को करने का सबसे अच्छा तरीका है।

दो लेखों को एक ही नाम (या जो भी विशिष्टता आपको चाहिए) को रोकने के लिए डेटाबेस में बाधा उत्पन्न करें। फिर, जब उपयोगकर्ता कोई नया आलेख बनाते हैं या किसी मौजूदा आलेख नाम के साथ मौजूदा अद्यतन करते हैं, तो डेटाबेस एक अपवाद फेंक देगा। उस अपवाद को पकड़ें और उपयोगकर्ता को इस मुद्दे के बारे में पता चले।

0

सामान्य गुण होने पर यह अच्छा होगा, लेकिन ऐसे समर्थित नहीं हैं। हालांकि, आप DbContext की Set विधि का उपयोग करने का प्रयास कर सकते हैं जो इकाई प्रकार को पैरामीटर के रूप में लेता है। गैर-जेनेरिक DbSet से पूछताछ करने के लिए आप System.Linq.Dynamic लाइब्रेरी का उपयोग कर सकते हैं (आप इसे NuGet से जोड़ सकते हैं)। यह स्ट्रिंग भविष्यवाणी का उपयोग कर DbSet से पूछताछ करने की अनुमति देता है।यहाँ एक उदाहरण है:

var existingEntityQuery = myContext.Set(validationContext.ObjectType) 
    .Where("Name= @0", (string)value); 
var enumerator = existingEntityQuery.GetEnumerator(); 

if (enumerator.MoveNext()) 
{ 
    var entity = enumerator.Current; 

    if (entity != null) 
    { 
     return new ValidationResult("The name already exist", propertiesList); 
    } 
} 
की
संबंधित मुद्दे