2011-04-04 15 views
30

मैं जानना चाहता हूं कि इकाई ढांचे और linq के साथ गतिशील क्वेरी बनाने का सबसे अच्छा तरीका क्या है।इकाई ढांचे के साथ गतिशील प्रश्न बनाना

मैं ऐसी सेवा बनाना चाहता हूं जिसमें सॉर्टिंग और फ़िल्टरिंग (50 से अधिक) के लिए कई पैरामीटर हैं। मुझे गुई से ऑब्जेक्ट मिल जाएगा जहां ये भर जाएंगे ... और क्वेरी को एक ही सेवा विधि से निष्पादित किया जाएगा।

मैंने चारों ओर देखा और मैंने देखा कि मैं गतिशील रूप से एक स्ट्रिंग बना सकता हूं जिसे मेरी विधि के अंत में निष्पादित किया जा सकता है। मुझे इस तरह से बहुत पसंद नहीं है। क्या ऐसा करने के लिए इससे अच्छा तरीका है? संकलन जांच के साथ पसंदीदा टाइप सुरक्षित?

उत्तर

45

आप IQueryable<T> चरण-दर-चरण लिख सकते हैं। मान लें कि आप एक FilterDefinition वर्ग जो बताती है कि उपयोगकर्ता फिल्टर करने के लिए चाहता है ...

public class FilterDefinition 
{ 
    public bool FilterByName { get; set; } 
    public string NameFrom { get; set; } 
    public string NameTo { get; set; } 

    public bool FilterByQuantity { get; set; } 
    public double QuantityFrom { get; set; } 
    public double QuantityTo { get; set; } 
} 

... तो आप तो जैसे एक प्रश्न बना सकते हैं:

public IQueryable<SomeEntity> GetQuery(FilterDefinition filter) 
{ 
    IQueryable<SomeEntity> query = context.Set<SomeEntity>(); 
    // assuming that you return all records when nothing is specified in the filter 

    if (filter.FilterByName) 
     query = query.Where(t => 
      t.Name >= filter.NameFrom && t.Name <= filter.NameTo); 

    if (filter.FilterByQuantity) 
     query = query.Where(t => 
      t.Quantity >= filter.QuantityFrom && t.Quantity <= filter.QuantityTo); 

    return query; 
} 
+0

धन्यवाद, लेकिन यह काम कैसे करता है? क्या यह डेटाबेस से सभी डेटा खींचता है और फिर चरण-दर-चरण इसे डेटा के वांछित सेट तक सीमित करता है ?? – Eduard

+7

@ टी-एडीडी: नहीं, यह 'स्थगित निष्पादन' (http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx) का लाभ उठाता है। इसका मतलब है कि 'IQueryable ' जो ऊपर दिए गए उदाहरण में बना है, केवल एक क्वेरी अभिव्यक्ति है जो वर्णन करती है कि डेटा फ़िल्टर कैसे किया जाता है। क्वेरी का असली निष्पादन बिल्कुल उदाहरण में नहीं है। उदाहरण के लिए 'query.oList() 'उदाहरण के लिए,' IQueryable 'पर" लालची "ऑपरेटर को लागू करके आप क्वेरी निष्पादित करते हैं। इस बिंदु पर - और पहले नहीं - क्वेरी अभिव्यक्ति का अनुवाद SQL में किया गया है और सर्वर पर भेजा गया है। – Slauma

+0

यह अच्छा नहीं है क्योंकि यह मानता है कि 'कुछ एंटीटीटी' में नाम और मात्रा फ़ील्ड हैं, इसलिए यह केवल आधा गतिशील है। –

1

आप डब्ल्यूसीएफ डेटा सेवाओं का उपयोग करके सेवा बनाने और गतिशील रूप से यूआरआई को अपने इकाई मॉडल से पूछने के लिए देख सकते हैं।

30

मुझे पता है कि एकमात्र अन्य तरीका आपके फ़िल्टर वाउज़ के आधार पर एक IQueryable बनाना होगा।

public List<Contact> Get(FilterValues filter) 
    { 
     using (var context = new AdventureWorksEntities()) 
     { 
      IQueryable<Contact> query = context.Contacts.Where(c => c.ModifiedDate > DateTime.Now); 

      if (!string.IsNullOrEmpty(filter.FirstName)) 
      { 
       query = query.Where(c => c.FirstName == filter.FirstName); 
      } 

      if (!string.IsNullOrEmpty(filter.LastName)) 
      { 
       query = query.Where(c => c.LastName == filter.LastName); 
      } 

      return query.ToList(); 
     } 
    } 
+0

हां, लेकिन क्या यह प्रभावशाली प्रदर्शन है? चयनित निष्पादित कब होता है? अंत में जब ToList() कहा जाता है? कल्पना कीजिए कि मेरे पास डेटा का बहुत बड़ा सेट है .... – Eduard

+1

नहीं, यह प्रदर्शन प्रदर्शन नहीं है, क्योंकि यह केवल एक बार क्वेरी करने के लिए स्थगित निष्पादन का उपयोग करता है। – BrandonZeider

+0

+1 अच्छे उत्तर के लिए धन्यवाद। – Eduard

4

आप गतिशील विनिर्देश और गतिशील उपयोग कर सकते हैं आदेश। मैंने उनके बारे में here और here ब्लॉग किया है। उदाहरण के नीचे की मदद करनी चाहिए हैं-

 //Assume you're getting following values from search form. 
     string userSuppliedProperty = "AverageRating"; 
     OperationType userSuppliedOperationType = OperationType.GreaterThan; 
     var userSuppliedValue = 4.5; 

     //Create DynamicSpecification from these properties and pass it to repository. 
     var userFilter = new DynamicSpecification<Product>(userSuppliedProperty, userSuppliedOperationType, userSuppliedValue); 
     var filteredProducts = _repository.Get(userFilter); 

     //You can also combine two specifications using either And or Or operation 
     string userSuppliedProperty2 = "Category"; 
     OperationType userSuppliedOperationType2 = OperationType.EqualTo; 
     var userSuppliedValue2 = "Keyboard"; 
     var userFilter2 = new DynamicSpecification<Product>(userSuppliedProperty2, userSuppliedOperationType2, userSuppliedValue2); 

     var combinedFilter = userFilter.And(userFilter2); 
     var filteredProducts2 = _repository.Get(combinedFilter); 

     //and it support dynamic sorting 
     string userSuppliedOrderingProperty = "Category"; 
     OrderType userSuppliedOrderType = OrderType.Ascending; 
     var sortedFilteredProducts = _repository.Get(combinedFilter, o => o.InOrderOf(userSuppliedOrderingProperty, userSuppliedOrderType)); 

मैं खोज वस्तु/डीटीओ आप हो रही है के बारे में पता नहीं है, लेकिन आप आसानी से एक सामान्य खोज वस्तु/डीटीओ बना सकते हैं और कुछ पंक्तियों में GenericSpecification की वस्तुओं की श्रृंखला के लिए यह मैप कर सकते हैं कोड का मैंने इसे डब्लूसीएफ सेवा के आसपास अतीत में इस्तेमाल किया है और उसने मेरे लिए बहुत अच्छा काम किया है।

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