5

डीएएल रिपोजिटरी द्वारा निर्माण करते समय, मैंने पाइप्स और फ़िल्टर नामक एक अवधारणा पर ठोकर खाई। मैंने इसके बारे में here पढ़ा, और here से एक स्क्रीनकास्ट देखा। मुझे अभी भी यकीन नहीं है कि इस पैटर्न को लागू करने के बारे में कैसे जाना है। सैद्धांतिक रूप से सभी अच्छा लगता है, लेकिन हम वास्तव में एक उद्यम परिदृश्य में इसे कैसे लागू करते हैं?आप LinqToSQL/Entity Framework/NHibernate के साथ पाइप्स और फ़िल्टर पैटर्न को कैसे कार्यान्वित करते हैं?

यदि आपके पास कोई प्रश्न, टिप्स या उदाहरण हैं, तो इस पैटर्न में डेटा मैपर्स/ओआरएम के संदर्भ में इस पैटर्न के लिए आरओ स्पष्टीकरण है।

अग्रिम धन्यवाद !!

+0

यदि आप किसी भी कारण से प्रश्न को कम करने का निर्णय लेते हैं तो कृपया एक टिप्पणी जोड़ें। – Perpetualcoder

+0

प्रश्न के साथ कुछ गलत है ?? – Perpetualcoder

उत्तर

11

आखिरकार, LINQ IEnumerable<T> एक पाइप और फ़िल्टर कार्यान्वयन है। IEnumerable<T>स्ट्रीमिंग एपीआई है - जिसका अर्थ यह है कि डेटा एक बार में सब कुछ लोड करने के बजाय, और रिकॉर्ड के बड़े बफर को लौटने के बजाय, इसके लिए पूछे जाने पर आलसी रूप से लौटाता है।

इसका मतलब है कि आपकी क्वेरी:

var qry = from row in source // IEnumerable<T> 
      where row.Foo == "abc" 
      select new {row.ID, row.Name}; 

है:

var qry = source.Where(row => row.Foo == "abc") 
      .Select(row = > new {row.ID, row.Name}); 

के रूप में आप इस पर गणना, यह lazily डेटा की खपत होगी। आप इसे जॉन स्कीट के Visual LINQ के साथ ग्राफिकल रूप से देख सकते हैं। पाइप तोड़ने वाली एकमात्र चीजें ऐसी चीजें हैं जो बफरिंग को मजबूर करती हैं; OrderBy, GroupBy, आदि। उच्च मात्रा के काम के लिए, जॉन और मैंने Push LINQ पर ऐसे परिदृश्यों में बफर किए बिना समेकन करने के लिए काम किया।

IQueryable<T> (अधिकांश ओआरएम उपकरण - LINQ-to-SQL, इकाई फ्रेमवर्क, LINQ-to-NHibernate द्वारा खुलासा) थोड़ा अलग जानवर है; क्योंकि डेटाबेस इंजन भारी भारोत्तोलन करने जा रहा है, संभावना है कि अधिकांश कदम पहले ही किए जा चुके हैं - जो कुछ भी बचा है, वह IDataReader का उपभोग करना है और इसे वस्तुओं/मूल्यों पर प्रोजेक्ट करना है - लेकिन यह अभी भी आमतौर पर एक पाइप है (IQueryable<T> लागू करता IEnumerable<T>) जब तक आप फोन .ToArray(), .ToList() आदि

उद्यम में उपयोग के संबंध में

... my view कि यह IQueryable<T> उपयोग करने के लिए भंडार के अंदर composable प्रश्नों लिखने के लिए ठीक है, लेकिन वे छुट्टी नहीं करना चाहिए भंडार - क्योंकि यह कॉलर के अधीन भंडार का आंतरिक संचालन करेगा, इसलिए आप क्लिंग करने के लिए लिया गया परीक्षण/प्रोफ़ाइल/ऑप्टिमाइज़/इत्यादि ठीक से यूनिट करने में असमर्थ होंगे। भंडार में हमेशा चीजें, लेकिन सूची सूचियों/सरणी। इसका मतलब यह भी है कि मेरा भंडार कार्यान्वयन से अनजान रहता है।

यह एक शर्म की बात है - क्योंकि IQueryable<T> को "वापसी" करने की प्रलोभन काफी बड़ी है; उदाहरण के लिए, यह कॉलर को पेजिंग/फ़िल्टर/आदि जोड़ने की अनुमति देगा - लेकिन याद रखें कि उन्होंने वास्तव में अभी तक डेटा का उपभोग नहीं किया है। यह संसाधन प्रबंधन को दर्द बनाता है। इसके अलावा, एमवीसी आदि में आपको यह सुनिश्चित करना होगा कि नियंत्रक.ToList() या इसी तरह के कॉल को कॉल करता है, ताकि यह डेटा दृश्य को नियंत्रित करने वाला दृश्य न हो (अन्यथा, फिर से, आप इकाई को नियंत्रक का ठीक से परीक्षण नहीं कर सकते)।

दाल में फिल्टर का एक सुरक्षित (IMO) उपयोग जैसी चीजों होगा: ऑन-द-मक्खी

public Customer[] List(string name, string countryCode) { 
    using(var ctx = new CustomerDataContext()) { 
     IQueryable<Customer> qry = ctx.Customers.Where(x=>x.IsOpen); 
     if(!string.IsNullOrEmpty(name)) { 
      qry = qry.Where(cust => cust.Name.Contains(name)); 
     } 
     if(!string.IsNullOrEmpty(countryCode)) { 
      qry = qry.Where(cust => cust.CountryCode == countryCode); 
     } 
     return qry.ToArray(); 
    } 
} 

यहाँ हम जोड़ दिया है फिल्टर, लेकिन कुछ नहीं होता जब तक हम ToArray कहते हैं। इस बिंदु पर, डेटा प्राप्त किया जाता है और लौटाया जाता है (प्रक्रिया में डेटा-संदर्भ का निपटान)। यह पूरी तरह से यूनिट परीक्षण किया जा सकता है। अगर हम कुछ इसी तरह की थी, लेकिन अभी IQueryable<T> लौटे, फोन करने वाले की तरह कुछ कर सकता:

var custs = customerRepository.GetCustomers() 
     .Where(x=>SomeUnmappedFunction(x)); 

और अचानक हमारे दाल में नाकाम रहने के लिए शुरू होता है के सभी (आदि TSQL को SomeUnmappedFunction अनुवाद नहीं कर सकता,)। आप अभी भी भंडार में दिलचस्प चीजों के बहुत कर सकते हैं।

यहां एकमात्र दर्द बिंदु यह है कि यह आपको विभिन्न कॉलिंग पैटर्न (पेजिंग के बिना/बिना) का समर्थन करने के लिए कुछ ओवरलोड करने के लिए प्रेरित कर सकता है। optional/named parameters तक पहुंचता है, मुझे इंटरफ़ेस पर एक्सटेंशन विधियों का उपयोग करने का सबसे अच्छा जवाब मिल गया है; कि जिस तरह से, मैं केवल एक ठोस भंडार कार्यान्वयन की जरूरत है:

class CustomerRepository { 
    public Customer[] List(
     string name, string countryCode, 
     int? pageSize, int? pageNumber) {...} 
} 
interface ICustomerRepository { 
    Customer[] List(
     string name, string countryCode, 
     int? pageSize, int? pageNumber); 
} 
static class CustomerRepositoryExtensions { 
    public static Customer[] List(
      this ICustomerRepository repo, 
      string name, string countryCode) { 
     return repo.List(name, countryCode, null, null); 
    } 
} 

अब हम आभासी भार के है (विस्तार के तरीकों के रूप में) ICustomerRepository पर - तो हमारे फोन करने वाले पेजिंग निर्दिष्ट किए बिना ही repo.List("abc","def") उपयोग कर सकते हैं।


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

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

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