रिपोजिटरी पैटर्न का उपयोग कब करें


20

मैंने हाल ही में पढ़ा है कि ओआरएम के साथ संयोजन में रिपॉजिटरी पैटर्न का उपयोग करना अच्छा नहीं है। मेरी समझ से यह इसलिए है क्योंकि एसक्यूएल डेटाबेस पर वे जो अमूर्तता प्रदान करते हैं, वह पैटर्न द्वारा निहित होने के लिए बहुत अधिक अस्थिर है।

मेरे पास इसके बारे में कुछ प्रश्न हैं:

  1. यदि आप ORMs स्विच करना चाहते हैं तो आप क्या करते हैं? यदि आपके पास रिपॉजिटरी में नहीं है, तो आपके आवेदन में ORM विशिष्ट कोड होगा।

  2. क्या ORM का उपयोग न करने पर रिपॉजिटरी पैटर्न अभी भी मान्य है और आप डेटा एक्सेस और स्वयं ऑब्जेक्ट डेटा को पॉप्युलेट करने के लिए ADO.NET का उपयोग कर रहे हैं?

  3. यदि आप एक ORM का उपयोग करते हैं, लेकिन रिपॉजिटरी पैटर्न का उपयोग नहीं करते हैं तो आप आमतौर पर उपयोग किए जाने वाले प्रश्नों को कहां रखते हैं? क्या प्रत्येक क्वेरी को एक वर्ग के रूप में प्रस्तुत करना बुद्धिमानी होगी और उदाहरण बनाने के लिए किसी प्रकार का क्वेरी कारखाना होना चाहिए?


1
1) आप कभी भी उनके अलग-अलग व्यवहारों के कारण एक ORM को स्वैप नहीं कर पाएंगे, भले ही दोनों linq का समर्थन करते हों, वे आपके आवेदन को तोड़ने के लिए अलग-अलग व्यवहार करेंगे। जैसे आलसी लोडिंग बिहेवियर, डर्टी ट्रैकिंग, घोस्ट प्रॉक्सिस इत्यादि .. हालांकि, परीक्षण के लिए इन-मेम कार्यान्वयन के लिए ORM को स्वैप करने में सक्षम होना अच्छा है ..
रोजर जोहानसन

इसके लायक क्या है, रिपोजिटरी / ओआरएम चर्चा पर मेरा विचार यहाँ है: stackoverflow.com/questions/13180501/…
एरिक किंग

आपने कहां पढ़ा कि यह एक बुरा अभ्यास है?
डेव हिलेर

जवाबों:


3

1) सच है, लेकिन आप कितनी बार एक ORM स्विच करते हैं?
2) मैं ऐसा कहूंगा, क्योंकि एक ORM संदर्भ एक रिपॉजिटरी की तरह है और बहुत सारे काम छिपाता है जिसमें प्रश्न बनाना, डेटा, मैपिंग, आदि को शामिल करना शामिल है। यदि आप ORM का उपयोग नहीं करते हैं, तो उस तर्क का अभी भी कहीं न कहीं निवास होता है। मुझे नहीं पता कि यह शब्द के सबसे कठिन अर्थों में रिपॉजिटरी पैटर्न के रूप में अर्हता प्राप्त करेगा या नहीं ...
3) प्रश्नों को एनकैप्सुलेट करना कुछ ऐसा है जो मैं अक्सर देखता हूं, लेकिन यह आमतौर पर परीक्षण / स्टबिंग उद्देश्यों के लिए अधिक होता है। इसके अलावा, किसी एप्लिकेशन के विभिन्न हिस्सों में किसी क्वेरी का पुन: उपयोग करते समय मैं सावधान रहूंगा, क्योंकि तब आप किसी ऐसी चीज पर निर्भरता पैदा करने का जोखिम उठाते हैं जो n-time (उन जगहों की संख्या होना जहां आप क्वेरी का उपयोग करते हैं) को बदल सकते हैं।


1
1) आप गलत सवाल पूछ रहे हैं। इससे कोई फर्क नहीं पड़ता कि कितनी बार, यह सिर्फ एक बार होना है। उपलब्ध ओआरएम विकल्पों की संख्या को देखते हुए, ऐसा कोई भी हो सकता है जो आप पहले से उपयोग कर रहे हैं उससे बेहतर है। सवाल अब यह हो जाता है: जब आप करते हैं तो क्या होता है? रिपोजिटरी आपको एक अच्छा अमूर्तता प्रदान करता है। मैं वहां गया हूं और मेरी इच्छा है कि मैं पहली बार इस तरह का अमूर्त बनाऊं।
देवनुल

3
@ देवनुल I असहमत। यदि यह एक बार में होता है, तो मैं इसे एक स्वीकार्य जोखिम मानता हूं। यदि आप गलत चुनाव करने से डरते हैं: एक करने से पहले अधिक प्रयोग करें। सिद्धांत रूप में, ऐसा अमूर्त अच्छा लगता है, लेकिन व्यवहार में आप अपने ORM के एपीआई के काफी बड़े हिस्से को फिर से बनाते हैं, क्योंकि आप किसी दिन किसी दूसरे को चुनने के लिए हवा निकाल सकते हैं। मेरे लिए, वह व्यर्थ प्रयास, निरर्थक कोड और अधिक कोड जो आपको स्वयं बनाए रखने और गारंटी देने के लिए है। इसके अलावा, एक ORM स्विच करने से एक संपूर्ण अनुप्रयोग प्रभावित नहीं होना चाहिए; डोमेन सीमाएँ रखना सीखें।
स्टीफन बिलियट

ओआरएम परिवर्तन रिपॉजिटरी का एकमात्र कारण नहीं है। यदि आपको अपने आवेदन में [वितरित] कैश को शुरू करने की आवश्यकता है - सभी परिवर्तन रिपॉजिटरी में किए जाएंगे और डेटा एक्सेस परत के परिवर्तनों के कारण आपका बीएल नहीं बदलेगा।
वल्र्ड

अधिकांश मामलों में वितरित कैश ORM में नहीं बनाया जा सकता है?
14:14 पर user1450877

मुझे लगता है कि यह ORM पर निर्भर करता है। आप NHibernate या EF की तुलना में लाइटर ORM के साथ जाने का निर्णय ले सकते हैं।
वल्र्ड

2

1) यदि आप ORM को बंद करना चाहते हैं तो आप क्या करते हैं, यदि आपके पास रिपॉजिटरी में नहीं है तो आपके आवेदन में विशिष्ट ORM कोड होगा।

मैं अभी तक ऐसी स्थिति में नहीं रहा हूँ जहाँ कंपनी ने अचानक डेटा एक्सेस तकनीक को स्विच करने का फैसला किया हो। यदि ऐसा होता है, तो कुछ काम की आवश्यकता होगी। मैं इंटरफेस के माध्यम से डेटा एक्सेस ऑपरेशन को अमूर्त करता हूं। इसे हल करने का एक तरीका है रिपॉजिटरी।

फिर मेरे डेटा एक्सेस लेयर के ठोस कार्यान्वयन के लिए एक अलग असेंबली होगी। उदाहरण के लिए, मेरे पास हो सकता है:

Company.Product.Dataऔर Company.Product.Data.EntityFrameworkविधानसभाएं। पहली असेंबली का उपयोग शुद्ध रूप से इंटरफेस के लिए किया जाएगा, जब दूसरा एंटिटी फ्रेमवर्क के डेटा एक्सेस लॉजिक का एक ठोस कार्यान्वयन होगा।

2) क्या ओआरएम का उपयोग नहीं करने पर रिपॉजिटरी पैटर्न अभी भी मान्य है और आप डेटा एक्सेस और स्वयं ऑब्जेक्ट डेटा को पॉप करने के लिए ADO.net का उपयोग कर रहे हैं?

मुझे लगता है कि यह तय करना आपके लिए है कि कौन सा पैटर्न वैध है या नहीं। मैंने प्रस्तुति परत में एक रिपॉजिटरी पैटर्न का उपयोग किया है। एक बात का ध्यान रखें कि लोग जिम्मेदारियों को रिपॉजिटरी में फेंकना पसंद करते हैं। इससे पहले कि आप इसे जानें, आपकी रिपॉजिटरी क्लास नृत्य, गायन और हर तरह की चीजें करेगी। आप इससे बचना चाहते हैं।

मैंने एक रिपॉजिटरी वर्ग देखा है जो GetAll, GetById, Update और Delete जिम्मेदारियों के होने से शुरू हुआ, जो ठीक है। जब तक यह परियोजना पूरी नहीं हुई, तब तक उसी वर्ग में दर्जनों विधियां (जिम्मेदारियां) थीं, जो कभी नहीं होनी चाहिए थीं। उदाहरण के लिए GetByForename, GetBySurname, UpdateWithExclusions और सभी प्रकार के पागल सामान।

यह वह जगह है जहाँ प्रश्न और आदेश चलन में आते हैं।

3) यदि आप एक ORM का उपयोग करते हैं, लेकिन रिपॉजिटरी पैटर्न का उपयोग नहीं करते हैं जहां आप आमतौर पर उपयोग किए जाने वाले प्रश्नों को रखते हैं। क्या प्रत्येक क्वेरी को एक वर्ग के रूप में प्रस्तुत करना बुद्धिमानी होगी और उदाहरण बनाने के लिए किसी प्रकार का क्वेरी कारखाना होना चाहिए?

मुझे लगता है कि रिपॉजिटरी के बजाय प्रश्नों और कमांड का उपयोग करना एक बहुत अच्छा विचार है। मैं निम्नलिखित कार्य करता हूं:

  • किसी क्वेरी के लिए इंटरफ़ेस परिभाषित करें। इससे आपको यूनिट टेस्ट में मदद मिलेगी। उदाहरण के लिएpublic interface IGetProductsByCategoryQuery { ... }

  • एक क्वेरी के लिए ठोस कार्यान्वयन को परिभाषित करें। आप अपनी पसंद के IoC फ्रेमवर्क के माध्यम से इन्हें इंजेक्ट कर पाएंगे। उदाहरण के लिएpublic class GetProductsByCategoryQuery : IGetProductsByCategoryQuery

अब दर्जनों जिम्मेदारियों के साथ रिपॉजिटरी को प्रदूषित करने के बजाय, मैं बस अपने प्रश्नों को नामस्थान में समूहित करता हूं। उदाहरण के लिए, उपरोक्त क्वेरी के लिए एक इंटरफ़ेस में रह सकता है: Company.SolutionName.Products.Queriesऔर कार्यान्वयन में रह सकता हैCompany.SolutionName.Products.Queries.Implementation

जब डेटा को अपडेट करने या हटाने की बात आती है, तो मैं उसी तरीके से कमांड पैटर्न का उपयोग करता हूं।

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


मुझे जेनेरिक फ़ंक्शंस के बजाय कमांड रखने का विचार पसंद है। डेटा एक्सेस के संदर्भ में उन्हें कैसे लागू किया जाए, इसके बारे में मैं और अधिक कहां पढ़ सकता हूं?
अंकुश

1

अस्वीकरण: क्या कहा जाता है मेरी समझ और उक्त पैटर्न के संक्षिप्त अनुभव (रिपॉजिटरी जो है) पर आधारित है। मैं इसे गलत कर सकता हूं ... वास्तव में, मैं बहुत सकारात्मक हूं कि मैं इसे गलत कर रहा हूं :)। तो, जबकि यह एक उत्तर के लिए एक प्रयास है, यह भी भेस में एक सवाल है।

मैं डेटा एक्सेस लेयर को दूर करने के लिए रिपॉजिटरी पैटर्न का उपयोग कर रहा हूं, जो कि ज्यादातर मामलों में ORM है। यह एक सामान्य इंटरफ़ेस है, जिसमें LINQ से SQL और EF के लिए अब तक क्रिएट, रीड, अपडेट, डिलीट और कार्यान्वयन कक्षाएं हैं। मैं एक कार्यान्वयन कर सकता हूं जो डिस्क पर XML फ़ाइलों को लिखता है (मैं इसके साथ क्या कर सकता था इसका सिर्फ एक जंगली उदाहरण)। ORM द्वारा समर्थित होने के बाद से मैं कार्य की इकाई को लागू नहीं कर रहा हूँ। अगर जरूरत पड़ी तो मैं इसे लागू कर सकता हूं। मुझे यह इस तरह से पसंद है क्योंकि, अब तक, इसने मुझे एक अच्छा अलगाव दिया है। मैं यह नहीं कह रहा हूं कि बेहतर विकल्प नहीं हैं।

अपने सवालों के जवाब देने के लिए:

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

आपको एक और उदाहरण देने के लिए, Umbraco के लोगों ने DI कंटेनर को दूर कर दिया है, बस अगर वे किसी और चीज़ पर स्विच करना चाहते हैं तो।


0

यदि ORM LINQ का लचीलापन, उत्सुक लोडिंग आदि प्रदान करता है, तो मैं इसे किसी भी अतिरिक्त परत के पीछे नहीं छिपाऊंगा।
यदि इसमें कच्चा एसक्यूएल (माइक्रो ओआरएम) शामिल है, तो "विधि प्रति क्वेरी" को वैसे भी पुन: प्रयोज्य प्राप्त करने के लिए उपयोग किया जाना चाहिए, इस प्रकार रिपॉजिटरी पैटर्न को एक अच्छा फिट बनाता है।

What do you do if you want to switch out ORMs? 
You would have ORM specific code in your application if you do not contain it in a repository.

आपको स्विच करने की आवश्यकता क्यों होगी?
आपको जिन सुविधाओं की सबसे अधिक आवश्यकता है, उनका उपयोग किया जाना चाहिए। यह संभव है कि ormX की एक नई रिलीज़ नई सुविधाएँ लाए और चालू से बेहतर हो, लेकिन ...
यदि आप orm को छुपाना चुनते हैं, तो आप केवल उन सभी सुविधाओं का उपयोग कर सकते हैं जो सभी उम्मीदवारों के पास समान हैं।
उदाहरण के लिए, आप Dictionary<string, Entity>अपनी संस्थाओं में संपत्तियों का उपयोग नहीं कर सकते क्योंकि ormY उन को नहीं संभाल सकता।

माना जाता है कि LINQ का उपयोग किया जाता है, ऑर्म स्विच का अधिकांश हिस्सा लाइब्रेरी संदर्भों को बदल रहा है और जब तक यह संकलित करता है तब तक या इसके session.Query<Foo>()साथ बदल रहा है context.Foos। बोरिंग कार्य, लेकिन अमूर्त परत को कोड करने की तुलना में कम समय लगता है।

Is the repository pattern still valid when not using an ORM and you are using ADO.NET for data access and populating object data yourself?

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

If you use an ORM but not the repository pattern where do you keep commonly used queries? 
Would it be wise to represent each query as a class and have some sort of query factory to create instances?

LINQ मान लिया जाता है कि एक क्लास रैपर IMHO ओवरकील होगा। एक अच्छा तरीका विस्तार तरीके होंगे

public static IQueryable<T> Published<T>(this IQueryable<T> source) where T : Page
{
    // at some point someone is going to forget to check that status
    // so it makes sense to extract this thing
    return source.Where(x => x.Status == Status.Published && x.PublishTime <= DateTime.UtcNow);
}

कोई भी कोड जो कई स्थानों पर उपयोग किया जाता है (या क्षमता है) और पर्याप्त जटिल है (त्रुटि प्रवण), एक केंद्रीय स्थान पर निकाला जाना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.