क्या स्रोत कोड में SQL लिखने के लिए इसे एक विरोधी पैटर्न माना जाता है?


87

क्या यह इस तरह से एक आवेदन में SQL हार्डकोड करने के लिए एक विरोधी पैटर्न माना जाता है:

public List<int> getPersonIDs()
{    
    List<int> listPersonIDs = new List<int>();
    using (SqlConnection connection = new SqlConnection(
        ConfigurationManager.ConnectionStrings["Connection"].ConnectionString))
    using (SqlCommand command = new SqlCommand())
    {
        command.CommandText = "select id from Person";
        command.Connection = connection;
        connection.Open();
        SqlDataReader datareader = command.ExecuteReader();
        while (datareader.Read())
        {
            listPersonIDs.Add(Convert.ToInt32(datareader["ID"]));
        }
    }
    return listPersonIDs;
}

मेरे पास सामान्य रूप से एक रिपॉजिटरी परत आदि होगी, लेकिन मैंने इसे सरलता के लिए ऊपर दिए गए कोड में शामिल नहीं किया है।

मुझे हाल ही में एक सहयोगी से कुछ प्रतिक्रिया मिली, जिसने शिकायत की थी कि SQL स्रोत कोड में लिखा गया था। मुझे यह पूछने का मौका नहीं मिला कि वह अब दो सप्ताह (शायद अधिक) के लिए दूर क्यों है। मुझे लगता है कि वह या तो मतलब था:

  1. LINQ
    या का उपयोग करें
  2. SQL के लिए संग्रहीत कार्यविधियों का उपयोग करें

क्या मैं सही हूँ? क्या स्रोत कोड में SQL लिखने के लिए इसे एक विरोधी पैटर्न माना जाता है? हम इस परियोजना पर काम करने वाली एक छोटी टीम हैं। संग्रहीत प्रक्रियाओं का लाभ मुझे लगता है कि एसक्यूएल डेवलपर्स विकास प्रक्रिया (संग्रहीत प्रक्रियाओं आदि को लिखने) के साथ जुड़ सकते हैं।

निम्न लिंक संपादित करें कड़ी कोडित SQL कथनों के बारे में बातचीत: https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/hard-coded-sql-statements । SQL स्टेटमेंट तैयार करने का कोई लाभ है?


31
"लाइनक का उपयोग करें" और "संग्रहीत प्रक्रियाओं का उपयोग करें" कारण नहीं हैं; वे सिर्फ सुझाव हैं। दो सप्ताह प्रतीक्षा करें, और उससे कारण पूछें।
रॉबर्ट हार्वे

47
स्टैक एक्सचेंज नेटवर्क एक माइक्रो-ओआरएम का उपयोग करता है जिसे डैपर कहा जाता है। मुझे लगता है कि यह कहना वाजिब है कि डैपर कोड का अधिकांश हिस्सा "हार्डकोडेड एसक्यूएल" (कमोबेश) है। तो अगर यह एक बुरा अभ्यास है, तो यह ग्रह पर सबसे प्रमुख वेब अनुप्रयोगों में से एक द्वारा अपनाया जाने वाला एक बुरा अभ्यास है।
रॉबर्ट हार्वे

16
रिपॉजिटरी के बारे में आपके सवाल का जवाब देने के लिए, हार्ड-कोडेड एसक्यूएल अभी भी हार्ड-कोडेड एसक्यूएल है, जहां आप इसे डालते हैं। अंतर यह है कि रिपॉजिटरी आपको हार्ड-कोडेड एसक्यूएल को एनकैप्सुलेट करने के लिए जगह देता है । यह अमूर्तता की एक परत है जो बाकी प्रोग्राम से SQL के विवरण को छुपाता है।
रॉबर्ट हार्वे

26
नहीं, कोड के भीतर SQL एक विरोधी पैटर्न नहीं है। लेकिन यह एक साधारण एसक्यूएल क्वेरी के लिए बॉयलर प्लेट कोड का एक बहुत कुछ है।
ग्रैंडमास्टरबी

45
'सोर्स कोड में' और 'सोर्स कोड में सभी में फैला हुआ' के बीच अंतर है
टोफ्रो

जवाबों:


112

आपने सादगी के लिए महत्वपूर्ण भाग को बाहर कर दिया। हठ के लिए भंडार अमूर्त परत है। हम दृढ़ता को अपनी परत में अलग करते हैं ताकि हम जरूरत पड़ने पर दृढ़ता प्रौद्योगिकी को अधिक आसानी से बदल सकें । इसलिए, दृढ़ता परत के बाहर SQL होने से एक अलग दृढ़ता परत होने के प्रयास को पूरी तरह से विफल कर देता है।

परिणामस्वरूप: SQL दृढ़ता परत के भीतर ठीक है जो SQL तकनीक के लिए विशिष्ट है (उदाहरण के लिए SQL ठीक है SQLCustomerRepositoryलेकिन एक में नहीं है MongoCustomerRepository)। दृढ़ता परत के बाहर, एसक्यूएल आपके अमूर्त को तोड़ता है और इस प्रकार बहुत बुरा अभ्यास माना जाता है (मेरे द्वारा)।

LINQ या JPQL जैसे उपकरणों के लिए: वे केवल SQL के जायके को अमूर्त कर सकते हैं। एक रिपॉजिटरी के बाहर LINQ-Code या JPQL क्वेश्चन होने से स्ट्रिक्ट एब्सट्रैक्शन उतना ही टूट जाता है, जितना कच्चा SQL होता है।


एक अलग दृढ़ता परत का एक और बड़ा लाभ यह है कि यह आपको एक डीबी सर्वर स्थापित किए बिना अपने व्यापार तर्क कोड को एकजुट करने की अनुमति देता है।

आपको कम मेमोरी-प्रोफ़ाइल मिलती है, आपकी भाषा का समर्थन करने वाले सभी प्लेटफार्मों पर प्रतिलिपि प्रस्तुत करने योग्य परिणामों के साथ तेज़ इकाई परीक्षण।

MVC + सेवा आर्किटेक्चर में यह रिपॉजिटरी उदाहरण का मजाक उड़ाने का एक सरल कार्य है, स्मृति में कुछ नकली-डेटा का निर्माण करना और यह परिभाषित करना कि रिपॉजिटरी को उस मॉक डेटा को वापस लौटना चाहिए जब एक निश्चित गटर कहा जाता है। फिर आप प्रति परीक्षण परीक्षण डेटा को परिभाषित कर सकते हैं और बाद में DB की सफाई के बारे में चिंता नहीं कर सकते।

DB के लिए परीक्षण लिखना उतना ही सरल है: यह सत्यापित करें कि दृढ़ता परत पर प्रासंगिक अद्यतन विधियों को बुलाया गया है और दावा किया है कि जब ऐसा हुआ था तब संस्थाएं सही स्थिति में थीं।


80
यह विचार कि "हम दृढ़ता प्रौद्योगिकी को बदल सकते हैं" वास्तविक दुनिया की अधिकांश परियोजनाओं में अवास्तविक और अनावश्यक है। एसक्यूएल / रिलेशनल डीबी नोंगक्यूबी डीबी जैसे मोंगोबीडी की तुलना में पूरी तरह से अलग जानवर है। इसके बारे में यह विस्तृत लेख देखें । अधिक से अधिक, एक परियोजना जो NoSQL का उपयोग करना शुरू कर देती है, अंततः उन्हें अपनी गलती का एहसास होगा और फिर RDBMS पर स्विच करना होगा। मेरे अनुभव में, व्यापार कोड से ऑब्जेक्ट-ओरिएंटेड क्वेरी लैंग्वेज (जैसे कि जेपीए-क्यूएल) का सीधे उपयोग करने की अनुमति देना सर्वोत्तम परिणाम प्रदान करता है।
रोजेरियो

6
क्या होगा अगर बहुत कम संभावना है कि दृढ़ता परत को बदल दिया जाए? क्या होगा अगर दृढ़ता परत को बदलते समय एक से एक मैपिंग न हो? एब्सट्रैक्शन के अतिरिक्त स्तर का क्या फायदा है?
pllee

19
@ Rogério NoSQL स्टोर से RDBMS या इसके विपरीत माइग्रेट कर रहा है, जैसा कि आप कहते हैं कि शायद यथार्थवादी नहीं है (यह मानते हुए कि प्रौद्योगिकी की पसंद शुरू करना उचित था)। हालाँकि, मैं कई वास्तविक विश्व परियोजनाओं में शामिल रहा हूँ जहाँ हम एक RDBMS से दूसरे में चले गए; उस परिदृश्य में, एक अतिक्रमित दृढ़ता परत निश्चित रूप से एक फायदा है।
डेविड

6
"यह विचार कि" हम दृढ़ता प्रौद्योगिकी को बदल सकते हैं "वास्तविक दुनिया की अधिकांश परियोजनाओं में अवास्तविक और अनावश्यक है।" मेरी कंपनी ने पहले उस धारणा के साथ कोड लिखा था। हमें एक नहीं, बल्कि तीन पूरी तरह से अलग-अलग स्टोरेज / क्वेरी सिस्टम को सपोर्ट करने के लिए पूरे कोडबेस को रिफलेक्टर करना था और तीसरे और चौथे पर विचार करना है। इससे भी बदतर, जब हमारे पास केवल एक डेटाबेस था, समेकन की कमी ने सभी प्रकार के कोड पापों को जन्म दिया।
एनपीएसएफ ३०००

3
@ Rogério आप "वास्तविक दुनिया की परियोजनाओं के विशाल बहुमत" जानते हैं? मेरी कंपनी में, अधिकांश एप्लिकेशन कई सामान्य डीबीएमएस में से एक के साथ काम कर सकते हैं, और यह बहुत उपयोगी है, क्योंकि ज्यादातर हमारे ग्राहकों के पास इसके संबंध में गैर-जरूरी आवश्यकताएं हैं।
बार्टोज़केपी

55

अधिकांश मानक व्यावसायिक अनुप्रयोग आज विभिन्न जिम्मेदारियों के साथ विभिन्न परतों का उपयोग करते हैं। हालाँकि, आप अपने एप्लिकेशन के लिए किन लेयर्स का उपयोग करते हैं, और किस लेयर की जिम्मेदारी आपकी और आपकी टीम पर है। इससे पहले कि आप SQL को सीधे उस फ़ंक्शन में रख सकें, जिसके बारे में आप निर्णय कर सकते हैं, जो आपने हमें दिखाया है, जिसे आपको जानना आवश्यक है

  • आपके आवेदन में किस परत पर कौन सी जिम्मेदारी है

  • किस परत से ऊपर का कार्य है

इसका कोई "एक-आकार-फिट-सभी" समाधान नहीं है। कुछ अनुप्रयोगों में डिजाइनर ORM फ्रेमवर्क का उपयोग करना पसंद करते हैं और फ्रेमवर्क को सभी SQL उत्पन्न करते हैं। कुछ अनुप्रयोगों में डिज़ाइनर ऐसी SQL को विशेष रूप से संग्रहीत कार्यविधियों में संग्रहीत करना पसंद करते हैं। कुछ अनुप्रयोगों के लिए जहाँ एसक्यूएल रहता है, वहाँ हाथ से लिखी दृढ़ता (या रिपॉजिटरी) परत होती है, और अन्य अनुप्रयोगों के लिए कुछ परिस्थितियों में अपवादों को सख्ती से परिभाषित करना एसक्यूएल को उस दृढ़ता परत में रखने से ठीक है।

तो आप क्या बारे में सोचने की जरूरत है: जो परतों है कि आप चाहते हैं या जरूरत अपने विशेष आवेदन में, और कैसे करते हैं आप जिम्मेदारियों करना चाहते हैं? आपने लिखा था "मेरे पास सामान्य रूप से एक रिपॉजिटरी लेयर होगी" , लेकिन आप उस लेयर के अंदर कौन सी सही जिम्मेदारियां रखना चाहते हैं और आप क्या जिम्मेदारियां रखना चाहते हैं? पहले उत्तर दें, फिर आप अपने प्रश्न का उत्तर स्वयं दे सकते हैं।


1
मैंने प्रश्न संपादित किया है। यकीन नहीं होता अगर यह किसी भी प्रकाश को बहा देता है।
w0051977

18
@ w0051977: आपके द्वारा पोस्ट किया गया लिंक हमें आपके आवेदन के बारे में कुछ नहीं बताता है , है ना? ऐसा लगता है कि आप एसक्यूएल जगह या जहां हर आवेदन के लिए फिट नहीं है, कुछ सरल, साहसी नियम की तलाश कर रहे हैं। वहां कोई नहीं है। यह एक डिजाइन निर्णय है जिसे आपको अपने व्यक्तिगत आवेदन के बारे में करना होगा (शायद आपकी टीम के साथ मिलकर)।
डॉक ब्राउन

7
+1। विशेष रूप से मैं यह नोट करूंगा कि किसी पद्धति में SQL और SQL के बीच कोई वास्तविक अंतर नहीं है, एक संग्रहीत कार्यविधि में, "हार्ड कोडित" के संदर्भ में कि कोई चीज़ कितनी कठोर है, या कैसे पुन: प्रयोज्य, बनाए रखने योग्य है, आदि। एक विधि के साथ प्रक्रिया की जा सकती है। बेशक प्रक्रियाएं उपयोगी हो सकती हैं, लेकिन एक रॉट नियम "हम विधियों में एसक्यूएल नहीं कर सकते हैं, तो चलो इसे सभी प्रक्रियाओं में डाल दें" शायद थोड़े से लाभ के साथ बहुत सारे cruft का उत्पादन करेंगे।

1
@ user82096 मैं कहूंगा कि आम तौर पर एसपी में डीबी एक्सेस कोड डालकर बोलना मेरे द्वारा देखे गए लगभग हर प्रोजेक्ट में हानिकारक है। (एमएस स्टैक) वास्तविक प्रदर्शन गिरावट (कठोर निष्पादन योजना कैश) के अलावा, सिस्टम का रखरखाव लॉजिक के आसपास विभाजित होने से कठिन बना दिया गया था, और एसपी ऐप लॉजिक डेवलपर्स की तुलना में लोगों के एक अलग सेट द्वारा बनाए रखा गया था। विशेष रूप से एज़्योर पर जहां तैनाती स्लॉट्स के बीच कोड परिवर्तन कार्य के सेकंड की तरह है, लेकिन स्लॉट्स के बीच गैर-कोड-प्रथम / डीबी-पहला स्कीमा माइग्रेशन एक परिचालन सिरदर्द का एक सा है।
प्रहरी

33

Marstato एक अच्छा जवाब देता है, लेकिन मैं कुछ और कमेंट्री जोड़ना चाहूंगा।

स्रोत में SQL एक विरोधी पैटर्न नहीं है, लेकिन यह समस्याओं का कारण बन सकता है। मुझे याद है जब आप एसक्यूएल प्रश्नों को हर फॉर्म पर गिराए गए घटकों के गुणों में डालते थे। इससे चीजें वास्तव में बहुत तेजी से बदली हैं और आपको प्रश्नों का पता लगाने के लिए हुप्स के माध्यम से कूदना पड़ा। मैं उन भाषाओं की सीमाओं के भीतर जितना संभव हो सके डेटाबेस एक्सेस को केंद्रीकृत करने का एक मजबूत समर्थक बन गया हो सकता है कि आपके सहकर्मी को इन काले दिनों में फ्लैशबैक मिल रहा हो।

अब, कुछ टिप्पणियाँ विक्रेता लॉक-इन के बारे में बात कर रहे हैं जैसे कि यह स्वचालित रूप से एक बुरी चीज है। यह नहीं है। अगर मैं ओरेकल का उपयोग करने के लिए हर साल एक छह आंकड़ा जांच कर रहा हूं, तो आप शर्त लगा सकते हैं कि मैं किसी भी एप्लिकेशन को उस डेटाबेस तक पहुंच बनाना चाहता हूं जो अतिरिक्त ओरेकल सिंटैक्स का उचित रूप से उपयोग कर रहा हो।लेकिन इसके पूर्ण करने के लिए। मुझे खुशी नहीं होगी अगर मेरा चमकदार डेटाबेस कोडर द्वारा वैनिला एएनएसआई एसक्यूएल को बुरी तरह से अपंग कर दिया जाए, जब एसक्यूएल लिखने का "ओरेकल तरीका" होता है जो डेटाबेस को अपंग नहीं करता है। हां, डेटाबेस बदलना कठिन होगा, लेकिन मैंने इसे केवल 20 वर्षों में कुछ समय में एक बड़े क्लाइंट साइट पर देखा है और उन मामलों में से एक DB2 से आगे बढ़ रहा था -> Oracle क्योंकि DB2 की मेजबानी करने वाली मेनफ्रेम अप्रचलित थी और डिकमीशन हो रही थी । हां, यह वेंडर लॉक-इन है, लेकिन कॉर्पोरेट ग्राहकों के लिए यह वास्तव में ओरेकल या माइक्रोसॉफ्ट एसक्यूएल सर्वर जैसे महंगे सक्षम आरडीबीएमएस के लिए भुगतान करने के लिए वांछनीय है और फिर इसे पूरी तरह से उपयोग करना है। आपके आराम कंबल के रूप में आपके पास एक समर्थन समझौता है। अगर मैं एक समृद्ध संग्रहीत कार्यविधि कार्यान्वयन वाले डेटाबेस के लिए भुगतान कर रहा हूं,

यह अगले बिंदु की ओर जाता है, यदि आप एक ऐसा एप्लिकेशन लिख रहे हैं जो SQL डेटाबेस तक पहुंचता है तो आपको एसक्यूएल के साथ-साथ अन्य भाषा भी सीखनी होगी और सीखने से मेरा मतलब क्वेरी ऑप्टिमाइज़ेशन भी होगा; यदि आप SQL पीढ़ी कोड लिखते हैं तो मैं आपसे नाराज हो जाऊंगा जो SQL कैश को लगभग समान प्रश्नों के बैराज के साथ फ्लश करता है जब आप एक चतुराई से पैरामीटर क्वेरी का उपयोग कर सकते थे।

कोई बहाना नहीं, हाइबरनेट की दीवार के पीछे कोई छिपाना नहीं। ORM बुरी तरह से उपयोग किया जा सकता है वास्तव में अनुप्रयोगों के प्रदर्शन को अपंग। मुझे याद है कि कुछ साल पहले स्टैक ओवरफ्लो पर एक प्रश्न देखा गया था:

हाइबरनेट में मैं 250,000 रिकॉर्ड के माध्यम से पुनरावृत्ति कर रहा हूं, कुछ गुणों के मूल्यों की जांच कर रहा है और कुछ शर्तों से मेल खाने वाली वस्तुओं को अपडेट कर रहा है। यह थोड़ा धीमा चल रहा है, मैं इसे गति देने के लिए क्या कर सकता हूं?

कैसे के बारे में "अद्यतन तालिका सेट फ़ील्ड 1 = जहां फ़ील्ड 2 ट्रू और फील्ड 3> 100" है। 250,000 वस्तुओं का निर्माण और निपटान अच्छी तरह से आपकी समस्या हो सकती है ...

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

तो, संक्षेप में, कोड में एसक्यूएल एम्बेड करना बुरा अभ्यास हो सकता है लेकिन बहुत खराब चीजें हैं जो आप एसक्यूएल से बचने की कोशिश कर सकते हैं।


5
मैंने यह नहीं कहा कि "वेंडर लॉक-इन" बुरी बात है। मैंने कहा कि यह व्यापार के साथ आता है। आज के बाजार में xaaS के रूप में db के साथ ऐसे पुराने अनुबंध और सेल्फहोस्टेड db चलाने के लाइसेंस अधिक से अधिक दुर्लभ होने जा रहे हैं। 10 साल पहले की तुलना में विक्रेता A से B में db को बदलना आज काफी आसान है। यदि आप टिप्पणियां पढ़ते हैं, तो मैं डेटा स्टोरेज की किसी भी सुविधा का लाभ लेने का पक्षधर हूं। इसलिए किसी विक्रेता (विक्रेता) के लिए कुछ विशिष्ट विक्रेता विवरण रखना आसान है, जिसका अर्थ विक्रेता अज्ञेय होना है। हम अंत में कोड का पालन करने के लिए एक एकल डेटा भंडारण के लिए कोड लॉक करने का प्रयास करते हैं। कोई बड़ी बात नहीं है
Laiv

2
यह एक बेहतरीन जवाब है। अक्सर सही दृष्टिकोण वह है जो सबसे खराब कोड की ओर जाता है अगर सबसे खराब संभव कोड लिखा जाता है। सबसे खराब संभव ORM कोड सबसे खराब संभव एम्बेडेड SQL से बहुत खराब हो सकता है।
jwg

@Laiv अच्छे अंक PaaS गेम चेंजर का एक सा है - मैं निहितार्थ के बारे में अधिक सोचना होगा।
एमकेटल

3
@jwg मैं यह कहना चाहूंगा कि औसत ORM कोड औसत से नीचे एम्बेडेड SQL :) से भी बदतर है
mcottle

@macottle यह मानते हुए कि एक ORM लिखने वाले के औसत से नीचे औसत एंबेडेड SQL ppl द्वारा लिखा गया था। मुझे इसमें बहुत संदेह है। कई देवता पहले तो बाहर की जाँच करने के लिए छोड़ दिया संयुक्त राज्य अमेरिका व्हाइटआउट लिखने में सक्षम नहीं हैं।
लाईव

14

हां, हार्ड कोडिंग एसक्यूएल स्ट्रिंग्स को एप्लिकेशन कोड में आमतौर पर एक विरोधी पैटर्न है।

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

रॉबर्ट सी। मार्टिन द्वारा स्वच्छ संहिता, स्नातकोत्तर।  288 (रॉबर्ट सी। मार्टिन को भाषाओं के मिश्रण पर, क्लीन कोड , अध्याय 17, "कोड स्मेल एंड हेयूरिस्टिक्स", पृष्ठ 288)

इस प्रतिक्रिया के लिए, मैं एसक्यूएल पर ध्यान केंद्रित करूंगा (जैसा कि प्रश्न में पूछा गया है)। निम्नलिखित मुद्दे तब हो सकते हैं जब SQL को असंतुष्ट तारों के एक ला कार्टे सेट के रूप में संग्रहीत किया जाता है:

  • डेटाबेस लॉजिक का पता लगाना मुश्किल है। आप अपने सभी SQL स्टेटमेंट को खोजने के लिए क्या खोजते हैं? "SELECT", "UPDATE", "MERGE", आदि के साथ स्ट्रिंग्स?
  • उसी या समान एसक्यूएल का उपयोग करना मुश्किल हो जाता है।
  • अन्य डेटाबेस के लिए समर्थन जोड़ना मुश्किल है। कोई इसे कैसे पूरा करेगा? प्रत्येक डेटाबेस के लिए if..then स्टेटमेंट जोड़ें और विधि में स्ट्रिंग्स के रूप में सभी प्रश्नों को संग्रहीत करें?
  • डेवलपर्स किसी अन्य भाषा में एक बयान पढ़ते हैं और विधि के उद्देश्य से विधि के कार्यान्वयन विवरण (कैसे और कहां से डेटा पुनर्प्राप्त किया जाता है) पर ध्यान केंद्रित करते हुए बदलाव से विचलित हो जाते हैं।
  • हालांकि एक-लाइनर एक समस्या का बहुत अधिक नहीं हो सकता है, क्योंकि स्टेटमेंट अधिक जटिल हो जाते हैं, इनलाइन एसक्यूएल तार टूटने लगते हैं। 113 लाइन स्टेटमेंट के साथ आप क्या करते हैं? अपनी विधि में सभी 113 लाइनें डालें?
  • डेवलपर अपने SQL संपादक (SSMS, SQL डेवलपर, आदि) और उनके स्रोत कोड के बीच प्रश्नों को कुशलतापूर्वक कैसे आगे बढ़ाता है? C # का @उपसर्ग आसान बनाता है, लेकिन मैंने बहुत सारे कोड देखे हैं जो प्रत्येक SQL लाइन को कोट करते हैं और नईलाइन्स से बच जाते हैं। "SELECT col1, col2...colN"\ "FROM painfulExample"\ "WHERE maintainability IS NULL"\ "AND modification.effort > @necessary"\
  • आस-पास के एप्लिकेशन कोड के साथ SQL को संरेखित करने के लिए उपयोग किए जाने वाले इंडेंटेशन वर्णों को प्रत्येक निष्पादन के साथ नेटवर्क पर प्रसारित किया जाता है। यह संभवतः छोटे पैमाने के अनुप्रयोगों के लिए नगण्य है, लेकिन यह सॉफ्टवेयर के उपयोग बढ़ने के साथ जोड़ सकता है।

पूर्ण ORMs (ऑब्जेक्ट-रिलेशनल मैपर्स जैसे कि एंटिटी फ्रेमवर्क या हाइबरनेट) एप्लिकेशन कोड में बेतरतीब ढंग से पेप्पर्ड एसक्यूएल को समाप्त कर सकते हैं। SQL और संसाधन फ़ाइलों का मेरा उपयोग एक उदाहरण है। ORMs, हेल्पर कक्षाएं, आदि सभी क्लीनर कोड के लक्ष्य को पूरा करने में मदद कर सकते हैं।

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

प्रोजेक्ट में SQL को रखने के कई सरल तरीके हैं। उन विधियों में से एक जो मैं अक्सर उपयोग करता हूं, प्रत्येक एसक्यूएल स्टेटमेंट को विजुअल स्टूडियो रिसोर्स फाइल में डालना है, जिसे आमतौर पर "sql" नाम दिया गया है। एक पाठ फ़ाइल, JSON दस्तावेज़, या अन्य डेटा स्रोत आपके टूल के आधार पर उचित हो सकता है। कुछ मामलों में, एसक्यूएल स्ट्रिंग्स को सुनिश्चित करने के लिए समर्पित एक अलग वर्ग सबसे अच्छा विकल्प हो सकता है, लेकिन ऊपर वर्णित मुद्दों में से कुछ हो सकता है।

SQL उदाहरण: जो अधिक सुरुचिपूर्ण दिखता है ?:

using(DbConnection connection = Database.SystemConnection()) {
    var eyesoreSql = @"
    SELECT
        Viewable.ViewId,
        Viewable.HelpText,
        PageSize.Width,
        PageSize.Height,
        Layout.CSSClass,
        PaginationType.GroupingText
    FROM Viewable
    LEFT JOIN PageSize
        ON PageSize.Id = Viewable.PageSizeId
    LEFT JOIN Layout
        ON Layout.Id = Viewable.LayoutId
    LEFT JOIN Theme
        ON Theme.Id = Viewable.ThemeId
    LEFT JOIN PaginationType
        ON PaginationType.Id = Viewable.PaginationTypeId
    LEFT JOIN PaginationMenu
        ON PaginationMenu.Id = Viewable.PaginationMenuId
    WHERE Viewable.Id = @Id
    ";
    var results = connection.Query<int>(eyesoreSql, new { Id });
}

हो जाता है

using(DbConnection connection = Database.SystemConnection()) {
    var results = connection.Query<int>(sql.GetViewable, new { Id });
}

एसक्यूएल हमेशा एक आसानी से मिल जाने वाली फाइल या फाइलों के समूह में सेट होता है, प्रत्येक एक वर्णनात्मक नाम के साथ होता है, जो यह बताता है कि यह क्या करता है, इसके बजाय प्रत्येक ऐसा करता है, जिसमें एक टिप्पणी के लिए स्थान होता है जो एप्लिकेशन कोड के प्रवाह को बाधित नहीं करेगा। :

एक संसाधन में एसक्यूएल

यह सरल विधि एकान्त क्वेरी को निष्पादित करती है। मेरे अनुभव में, "विदेशी भाषा" के उपयोग के रूप में लाभ तराजू अधिक परिष्कृत होता है। संसाधन फ़ाइल का मेरा उपयोग केवल एक उदाहरण है। भाषा (SQL इस मामले में) और प्लेटफॉर्म के आधार पर अलग-अलग तरीके अधिक उपयुक्त हो सकते हैं।

यह और अन्य तरीके उपरोक्त सूची को निम्नलिखित तरीके से हल करते हैं:

  1. डेटाबेस कोड का पता लगाना आसान है क्योंकि यह पहले से ही केंद्रीकृत है। बड़ी परियोजनाओं में, अलग-अलग फ़ाइलों में एसक्यूएल जैसे समूह, शायद नाम के एक फ़ोल्डर के तहत SQL
  2. एक दूसरे, तीसरे, आदि डेटाबेस के लिए समर्थन आसान है। एक इंटरफ़ेस (या अन्य भाषा अमूर्त) बनाएं जो प्रत्येक डेटाबेस के अद्वितीय विवरणों को लौटाता है। प्रत्येक डेटाबेस के लिए कार्यान्वयन समान बयानों की तुलना में थोड़ा अधिक हो जाता है: return SqlResource.DoTheThing;सच है, ये कार्यान्वयन संसाधन को छोड़ सकते हैं और SQL को एक स्ट्रिंग में शामिल कर सकते हैं, लेकिन ऊपर कुछ (सभी नहीं) समस्याएं अभी भी सतह पर होंगी।
  3. Refactoring सरल है - बस उसी संसाधन का पुन: उपयोग करें। तुम भी कुछ प्रारूप बयान के साथ समय के विभिन्न DBMS सिस्टम के लिए एक ही संसाधन प्रविष्टि का उपयोग कर सकते हैं। मैं अक्सर ऐसा करता हूं।
  4. द्वितीयक भाषा का उपयोग वर्णनात्मक नामों का उपयोग कर सकता है, उदाहरण के लिए sql.GetOrdersForAccountअधिक उपयोग के बजायSELECT ... FROM ... WHERE...
  5. एसक्यूएल बयानों को उनके आकार और जटिलता की परवाह किए बिना एक पंक्ति में बुलाया जाता है।
  6. एसक्यूएल को एसएसएमएस और एसक्यूएल डेवलपर जैसे डेटाबेस टूल्स के बीच कॉपी और पेस्ट किया जा सकता है। कोई उद्धरण चिह्न नहीं। कोई पीछे की ओर नहीं। विशेष रूप से Visual Studio संसाधन संपादक के मामले में, एक क्लिक SQL कथन पर प्रकाश डालता है। CTRL + C और फिर इसे SQL एडिटर में पेस्ट करें।

किसी संसाधन में SQL का निर्माण त्वरित है, इसलिए SQL-इन-कोड के साथ संसाधन उपयोग को मिलाने के लिए बहुत कम प्रोत्साहन है।

चुने हुए तरीके के बावजूद, मैंने पाया है कि भाषाओं का मिश्रण आमतौर पर कोड की गुणवत्ता को कम करता है। मुझे उम्मीद है कि यहाँ वर्णित कुछ मुद्दे और समाधान डेवलपर्स को उपयुक्त होने पर इस कोड की गंध को खत्म करने में मदद करते हैं।


13
मुझे लगता है कि स्रोत कोड में SQL होने की बुरी आलोचना पर यह बहुत अधिक ध्यान केंद्रित करता है। एक ही फाइल में दो अलग-अलग भाषाओं का होना जरूरी नहीं है। यह बहुत सी बातों पर निर्भर करता है जैसे कि वे कैसे संबंधित हैं और वे प्रत्येक कैसे प्रस्तुत हैं।
jwg

9
"एक ही फाइल में अलग-अलग वाक्यविन्यास के साथ पूरी तरह से अलग-अलग भाषाओं का मिश्रण" यह एक भयानक तर्क है। यह रेज़र व्यू इंजन और HTML, CSS और जावास्क्रिप्ट पर भी लागू होगा। अपने ग्राफिक उपन्यासों से प्यार करें!
इयान न्यूज़न

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

3
स्पष्ट होने के लिए, यह प्रश्न का उत्तर नहीं है "मैं अपने एसक्यूएल स्ट्रिंग्स के साथ क्या करता हूं," इतना ही नहीं यह प्रश्न का उत्तर है "मैं पर्याप्त रूप से जटिल स्ट्रिंग्स के किसी भी संग्रह के साथ क्या करता हूं," एक सवाल जो आपका उत्तर स्पष्ट रूप से संबोधित करता है।
रॉबर्ट हार्वे

2
@ रोबर्टहाइवे: मुझे यकीन है कि हमारे अनुभव अलग-अलग हैं, लेकिन मेरे खुद के सवाल में मैंने पाया है कि ज्यादातर मामलों में जीत एक सवाल है। मैं अपने अमूर्त व्यापार को निश्चित रूप से परिष्कृत करूंगा जैसा कि मैंने वर्षों तक किया है, और एक दिन एसक्यूएल को कोड में वापस रख सकता हूं। YMMV। :) मुझे लगता है कि microservices महान हो सकता है, और वे आम तौर पर आपके SQL विवरण (यदि SQL सभी में उपयोग किया जाता है) को मुख्य एप्लिकेशन कोड से अलग करते हैं। मैं कम वकालत कर रहा हूं "अपनी विशिष्ट विधि का उपयोग करें: संसाधन" और अधिक वकालत "आम तौर पर तेल और पानी की भाषाएं नहीं मिलाते हैं।"
चार्ल्स बर्न्स

13

निर्भर करता है। कई अलग-अलग दृष्टिकोण हैं जो काम कर सकते हैं:

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

जैसा कि अक्सर होता है, यदि आपकी परियोजना ने इनमें से किसी एक तकनीक को पहले ही चुना है, तो आपको बाकी परियोजना के अनुरूप होना चाहिए।

(1) और (3) दोनों ही एप्लीकेशन लॉजिक और डेटाबेस के बीच स्वतंत्रता बनाए रखने में अपेक्षाकृत अच्छे हैं, इस अर्थ में कि अगर आप किसी अलग वेंडर के साथ डेटाबेस को बदलते हैं तो एप्लिकेशन बेसिक स्मोक टेस्ट को कंपाइल और पास करता रहेगा। हालांकि, अधिकांश विक्रेता पूरी तरह से SQL मानक के अनुरूप नहीं होते हैं, इसलिए किसी भी विक्रेता को किसी अन्य विक्रेता के साथ बदलने के लिए व्यापक परीक्षण और बग शिकार की आवश्यकता होती है, भले ही आप किस तकनीक का उपयोग करें। मुझे संदेह है कि यह एक सौदे के रूप में बड़ा है क्योंकि लोग इसे पूरा करते हैं। डेटाबेस बदलना मूल रूप से एक अंतिम उपाय है जब आप अपनी जरूरतों को पूरा करने के लिए वर्तमान डेटाबेस प्राप्त नहीं कर सकते। यदि ऐसा होता है, तो आपने संभवतः डेटाबेस को खराब तरीके से चुना है।

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

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

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

रीड्स के लिए, संग्रहीत प्रक्रियाएं मूल रूप से (2) का क्रैपीयर संस्करण हैं। मैं उन्हें उस क्षमता में अनुशंसा नहीं करता, लेकिन आप अभी भी उन्हें लिखना चाहते हैं, यदि आपका डेटाबेस अद्यतन योग्य विचारों का समर्थन नहीं करता है , या यदि आपको एक बार में एक पंक्ति डालने या अपडेट करने की तुलना में कुछ अधिक जटिल करने की आवश्यकता है (जैसे लेन-देन, पढ़ना-फिर-लिखना, आदि)। आप एक ट्रिगर (यानी) का उपयोग करके अपनी संग्रहीत प्रक्रिया को एक दृश्य में जोड़ सकते हैंCREATE TRIGGER trigger_name INSTEAD OF INSERT ON view_name FOR EACH ROW EXECUTE PROCEDURE procedure_name;), लेकिन राय में काफी भिन्नता है कि क्या यह वास्तव में एक अच्छा विचार है। प्रस्तावक आपको बताएंगे कि यह एसक्यूएल रखता है कि आपका आवेदन यथासंभव सरल है। डिटेक्टर्स आपको बताएंगे कि यह "जादू" का एक अस्वीकार्य स्तर है और आपको बस अपने आवेदन से सीधे प्रक्रिया को निष्पादित करना चाहिए। मैं कहता हूँ कि हम इस एक बेहतर विचार है अपने संग्रहीत प्रक्रिया लग रहा है, तो या एक तरह एक बहुत काम करता है INSERT, UPDATEया DELETE, और एक बुरा विचार यह कुछ और कर रहा है। अंततः आपको खुद तय करना होगा कि कौन सी शैली अधिक समझ में आती है।

(४) निराकार है। यह छोटी परियोजनाओं, या बड़े लोगों के लिए इसके लायक हो सकता है जो केवल डेटाबेस के साथ छिटपुट रूप से बातचीत करते हैं। लेकिन बहुत सारे एसक्यूएल वाली परियोजनाओं के लिए, यह एक अच्छा विचार नहीं है क्योंकि आपके पास अपने आवेदन के चारों ओर बिखरे हुए एक ही क्वेरी के डुप्लिकेट या रूपांतर हो सकते हैं, जो पठनीयता और रीफैक्टरिंग के साथ हस्तक्षेप करता है।


2 जैसा कि लिखा गया है, केवल एक डेटाबेस को रीड करता है। संशोधित प्रक्रियाओं का उपयोग उन प्रश्नों के लिए असामान्य नहीं है जो संशोधित करते हैं।
jpmc26

@ jpmc26: मैं कवर करता हूं कि पैतृक में लिखते हैं ... क्या आपके पास इस उत्तर को बेहतर बनाने के लिए एक विशिष्ट सिफारिश है?
केविन

हम्म। जवाब पूरा करने से पहले टिप्पणी करने और फिर विचलित होने के लिए माफी। लेकिन अद्यतन करने योग्य दृश्य जहां एक तालिका को अद्यतन किया जा रहा है, उसे नीचे ट्रैक करना मुश्किल बनाते हैं। तंत्र की परवाह किए बिना, तालिकाओं पर सीधे अपडेट को प्रतिबंधित करना, कोड लॉजिक को समझने के संदर्भ में इसके फायदे हैं। यदि आप DB को तर्क देने के लिए विवश कर रहे हैं, तो, आप इसे संग्रहीत प्रक्रियाओं के बिना लागू नहीं कर सकते। उन्हें एकल कॉल के साथ कई ऑपरेशनों की अनुमति देने का लाभ भी है। नीचे पंक्ति: मुझे नहीं लगता कि आपको उन पर इतना कठोर होना चाहिए।
jpmc26

@ jpmc26: यह उचित है।
केविन

8

क्या सोर्स कोड में SQL लिखने के लिए इसे एक एंटी-पैटर्न माना जाता है?

जरुरी नहीं। यदि आप यहां सभी टिप्पणियों को पढ़ते हैं, तो आपको स्रोत कोड में SQL बयानों को हार्डकोड करने के लिए मान्य तर्क मिलेंगे।

समस्या यह है कि आप बयानों को कहां रखते हैं । यदि आप प्रोजेक्ट में सभी जगह SQL कथन रखते हैं, तो आप शायद कुछ ठोस सिद्धांतों की अनदेखी कर रहे हैं जिन्हें हम आमतौर पर पालन करने का प्रयास करते हैं।

मान लें कि उसका मतलब था; या तो:

1) LINQ का उपयोग करें

या

2) SQL के लिए संग्रहीत कार्यविधियों का उपयोग करें

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

यह जरूरी गलत नहीं है और न ही बुरा है। मैं सिर्फ तथ्य की ओर इशारा कर रहा हूं।

SOLID सिद्धांतों और विक्रेता के ताले को अनदेखा करना संभव प्रतिकूल परिणाम हैं जिन्हें आप अनदेखा कर सकते हैं। इसलिए आमतौर पर टीम के साथ बैठना और अपनी शंकाओं को उजागर करना अच्छा होता है।

संग्रहीत प्रक्रियाओं का लाभ मुझे लगता है कि SQL डेवलपर्स विकास प्रक्रिया (संग्रहीत कार्यविधियाँ लिखना) के साथ शामिल हो सकते हैं

मुझे लगता है कि संग्रहीत प्रक्रियाओं के फायदे से इसका कोई लेना-देना नहीं है। इसके अलावा, यदि आपके सहयोगी ने हार्डकोड SQL को नापसंद किया है, तो यह संभव है कि व्यवसाय को संग्रहीत प्रक्रियाओं में स्थानांतरित करना उसे भी नापसंद होगा।

संपादित करें: निम्न लिंक हार्ड-कोडित SQL स्टेटमेंट्स के बारे में बात करता है:  https://docs.microsoft.com/en-us/sql/odbc/reference/develop-app/hard-coded-sql-statements । SQL स्टेटमेंट तैयार करने का कोई लाभ है?

हाँ। पोस्ट में तैयार कथनों के फायदे शामिल हैं । यह SQL टेम्प्लेटिंग का एक प्रकार है। तार संयोजन की तुलना में अधिक सुरक्षित। लेकिन पोस्ट आपको इस तरह जाने के लिए प्रोत्साहित नहीं कर रहा है और न ही यह पुष्टि कर रहा है कि आप सही हैं। यह सिर्फ यह बताता है कि हम एक सुरक्षित और कुशल तरीके से हार्डकोड SQL का उपयोग कैसे कर सकते हैं।

संक्षेप में, अपने सहयोगी से पहले पूछने का प्रयास करें। एक मेल भेजें, उसे फोन करें, ... वह जवाब देता है या नहीं, टीम के साथ बैठें और अपनी शंकाओं को उजागर करें। उस समाधान को ढूंढें जो आपकी आवश्यकताओं को सबसे अच्छा करता है। आप वहां जो पढ़ते हैं, उसके आधार पर गलत धारणाएं न बनाएं।


1
धन्यवाद। +1 के लिए "हार्डकोडिंग एसक्यूएल स्टेटमेंट आपको अपने एप्लिकेशन को डीबी इंजीनियर को कसकर युग्मन करने के लिए प्रेरित कर सकता है।" अगर वह एसक्यूएल के बजाय एसक्यूएल सर्वर का जिक्र कर रहा है तो मैं भटक रहा हूं। SQLCommand बजाय dbCommand और SQLDataReader के बजाय dbDataReader।
w0051977

नहीं, मैं गैर-एएनएसआई अनुरूप अभिव्यक्तियों के उपयोग का उल्लेख कर रहा था। उदाहरण के लिए: select GETDATE(), ....GETDATE () SqlServer का दिनांक फ़ंक्शन है। अन्य इंजनों में, फ़ंक्शन का अलग-अलग नाम, अलग-अलग अभिव्यक्ति है, ...
Laiv

14
"विक्रेता लॉक-इन" ... लोग / उद्यम वास्तव में अपने मौजूदा उत्पाद के डेटाबेस को किसी अन्य RDBMS में कैसे स्थानांतरित करते हैं? यहां तक ​​कि विशेष रूप से ओआरएम का उपयोग करने वाली परियोजनाओं में, मैंने कभी ऐसा नहीं देखा था: आमतौर पर सॉफ्टवेयर को स्क्रैच से भी फिर से लिखा जाता है, क्योंकि बीच में जरूरतें बदल गई हैं। इसलिए, इस बारे में सोचना मेरे लिए "प्रीमेच्योर ऑप्टिमाइज़ेशन" जैसा लगता है। हाँ, यह पूरी तरह से व्यक्तिपरक है।
ओलिवियर ग्रेगोइरे

1
मुझे परवाह नहीं है कि कितनी बार होता है। मुझे परवाह है कि ऐसा हो सकता है। ग्रीनफील्ड परियोजनाओं में, डीबी से डीएएल को लागू करने की लागत लगभग 0. है। संभावित प्रवासन नहीं है। ओआरएम के खिलाफ तर्क काफी कमजोर हैं। ORMs 15 साल पहले की तरह नहीं हैं जब हाइबरनेट काफी हरा था। मैंने जो कुछ देखा है वह "डिफ़ॉल्ट रूप से" कॉन्फ़िगरेशन और बहुत अधिक खराब डेटा मॉडल डिज़ाइन का एक बहुत है। यह कई अन्य उपकरणों की तरह है, बहुत से लोग "आरंभ करना" ट्यूटोरियल करते हैं और उन्हें परवाह नहीं है कि हुड के नीचे क्या होता है। उपकरण समस्या नहीं है। समस्या यह है कि इसका उपयोग कैसे और कब किया जाए, यह कोई नहीं जानता।
लाईव

दूसरी ओर, वेंडर लॉक-इन जरूरी बुरा नहीं है। अगर मुझसे पूछा गया तो मैं कहूंगा कि मुझे पसंद नहीं है । हालाँकि, मैं पहले से ही स्प्रिंग, टॉम्कट या जेबॉस या वेब्सफ़ेयर (अभी भी बदतर) में बंद हूँ। जिन्हें मैं टाल सकता हूं, मैं करता हूं। जिन्हें मैं नहीं कर सकता, मैं इसके साथ रह सकता हूं। यह वरीयताओं की बात है।
लाईव

3

मुझे लगता है कि यह एक बुरा अभ्यास है, हां। दूसरों ने आपके सभी डेटा एक्सेस कोड को अपनी परत में रखने के फायदे बताए हैं। आपको इसके लिए शिकार करने की ज़रूरत नहीं है, इसे अनुकूलित करना और परीक्षण करना आसान है ... लेकिन उस परत के भीतर भी, आपके पास कुछ विकल्प हैं: ORM का उपयोग करें, स्प्रोक्स का उपयोग करें, या SQL क्वेरी को स्ट्रिंग्स के रूप में एम्बेड करें। मैं कहूंगा कि SQL क्वेरी स्ट्रिंग्स अब तक सबसे खराब विकल्प हैं।

ओआरएम के साथ, विकास बहुत आसान हो जाता है, और कम त्रुटि वाला। EF के साथ, आप अपने मॉडल वर्गों को बनाकर अपने स्कीमा को परिभाषित करते हैं (आपको वैसे भी इन कक्षाओं को बनाने की आवश्यकता होगी)। LINQ के साथ क्वेरी करना एक हवा है - आप अक्सर c # की 2 पंक्तियों के साथ दूर हो जाते हैं, जहां आपको अन्यथा लिखने और स्पार्क बनाए रखने की आवश्यकता होती है। IMO, इसका एक बड़ा फायदा है जब यह उत्पादकता और स्थिरता के लिए आता है - कम कोड, कम समस्याएं। लेकिन एक प्रदर्शन ओवरहेड है, भले ही आपको पता हो कि आप क्या कर रहे हैं।

स्पोक (या फ़ंक्शंस) अन्य विकल्प हैं। यहां, आप अपने SQL प्रश्नों को मैन्युअल रूप से लिखते हैं। लेकिन कम से कम आपको कुछ गारंटी मिलती है कि वे सही हैं। यदि आप .NET में काम कर रहे हैं, तो विजुअल स्टूडियो भी SQL गलत होने पर कंपाइलर त्रुटियों को फेंक देगा। यह भी खूब रही। यदि आप कुछ कॉलम को बदलते या निकालते हैं, और आपके कुछ प्रश्न अमान्य हो जाते हैं, तो कम से कम आपको संकलन समय के दौरान इसके बारे में पता चलने की संभावना है। अपनी खुद की फाइलों में स्पोक बनाए रखना भी आसान है - आपको सिंटैक्स हाइलाइटिंग, स्वतः पूर्ण ..etc मिलेगा।

यदि आपके प्रश्नों को स्प्रोक्स के रूप में संग्रहीत किया जाता है, तो आप उन्हें पुन: संकलित किए बिना और एप्लिकेशन को फिर से तैनात किए बिना भी बदल सकते हैं। यदि आप देखते हैं कि आपकी SQL में कुछ टूट गया है, तो एक DBA आपके ऐप कोड तक पहुँच की आवश्यकता के बिना इसे ठीक कर सकता है। सामान्य तौर पर, यदि आपके प्रश्न स्ट्रिंग के शाब्दिक हैं, तो आप dbas अपना काम लगभग आसानी से नहीं कर सकते हैं।

स्ट्रिंग शाब्दिक के रूप में एसक्यूएल क्वेरी भी आपके डेटा एक्सेस सी # कोड को कम पठनीय बनाएगी।

बस अंगूठे के एक नियम के रूप में, जादू स्थिरांक खराब हैं। जिसमें स्ट्रिंग शाब्दिक शामिल हैं।


एप्लिकेशन को अपडेट किए बिना अपने एसक्यूएल को बदलने के लिए डीबीए की अनुमति देना आपके आवेदन को प्रभावी रूप से दो अलग-अलग विकसित, अलग से तैनात संस्थाओं में विभाजित कर रहा है। अब आपको उन लोगों के बीच इंटरफ़ेस अनुबंध का प्रबंधन करने की आवश्यकता है, अन्योन्याश्रित परिवर्तनों की रिहाई को सिंक्रनाइज़ करें, आदि यह एक अच्छी बात या बुरी बात हो सकती है, लेकिन यह "आपके सभी एसक्यूएल को एक जगह पर रखने" की तुलना में बहुत अधिक है, यह बहुत दूर है। -विस्तृत वास्तु निर्णय।
IMSoP

2

यह एक विरोधी पैटर्न नहीं है (यह जवाब खतरनाक रूप से राय के करीब है)। लेकिन कोड स्वरूपण महत्वपूर्ण है, और SQL स्ट्रिंग को स्वरूपित किया जाना चाहिए ताकि यह उस कोड से स्पष्ट रूप से अलग हो जो इसे उपयोग करता है। उदाहरण के लिए

    string query = 
    @"SELECT foo, bar
      FROM table
      WHERE id = @tn";

7
इसके साथ सबसे अधिक समस्या यह है कि 42 का मूल्य कहां से आता है। क्या आप उस मान को स्ट्रिंग में परिवर्तित कर रहे हैं? यदि हां, तो यह कहां से आया है? SQL इंजेक्शन हमलों को कम करने के लिए इसे कैसे साफ़ किया गया है? यह उदाहरण एक मानकीकृत क्वेरी क्यों नहीं दिखाता है?
क्रेग

मेरा मतलब सिर्फ फॉर्मेटिंग दिखाना था। क्षमा करें, मैं इसे मानकीकृत करना भूल गया। अब msdn.microsoft.com/library/bb738521(v=vs.100).aspx
rleir

स्वरूपण के महत्व के लिए +1, हालांकि मैं यह सुनिश्चित करता हूं कि SQL स्ट्रिंग स्वरूपण की परवाह किए बिना एक कोड गंध है।
चार्ल्स बर्न्स

1
क्या आप ORM के उपयोग पर जोर देते हैं? जब एक ORM उपयोग में नहीं होता है, तो एक छोटी परियोजना के लिए, मैं एम्बेडेड SQL युक्त 'शिम' क्लास का उपयोग करता हूं।
रीलेयर

SQL स्ट्रिंग्स सबसे निश्चित रूप से एक कोड गंध नहीं हैं। एक ORM के बिना, एक प्रबंधक और वास्तुकार के रूप में मैं उन्हें रखरखाव और कभी-कभी प्रदर्शन कारणों के लिए SPs पर प्रोत्साहित करूंगा।
सेंटिनल

1

मैं आपको यह नहीं बता सकता कि आपके सहयोगी का क्या मतलब है। लेकिन मैं इसका जवाब दे सकता हूं:

SQL स्टेटमेंट तैयार करने का कोई लाभ है?

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

... और क्वेरी स्ट्रिंग्स के बुरे संघटन के लिए सबसे प्रभावी बचाव पहली बार में स्ट्रिंग्स के रूप में प्रश्नों का प्रतिनिधित्व नहीं कर रहा है, लेकिन प्रश्नों के निर्माण के लिए एक प्रकार-सुरक्षित क्वेरी एपीआई का उपयोग करना है। उदाहरण के लिए, यहाँ बताया गया है कि मैं जावा में आपकी क्वेरी QueryDSL के साथ कैसे लिखूंगा:

List<UUID> ids = select(person.id).from(person).fetch();

जैसा कि आप देख सकते हैं, यहां एक भी स्ट्रिंग शाब्दिक नहीं है, जिससे SQL इंजेक्शन नायकों को असंभव बना दिया जा सकता है। इसके अलावा, मुझे यह लिखते समय कोड पूरा हो गया था, और मेरी आईडीई इसे रिफ्लेक्टर कर सकती है, जिसे मुझे आईडी कॉलम का नाम बदलने के लिए चुनना चाहिए। साथ ही, मैं अपनी IDE पूछकर व्यक्ति तालिका के लिए सभी प्रश्नों को आसानी से पा सकता हूं जहां personचर एक्सेस किया गया है। ओह, और क्या आपने देखा कि यह आपके कोड की तुलना में आंखों पर काफी छोटा और आसान है?

मैं केवल यह मान सकता हूं कि ऐसा कुछ C # के लिए भी उपलब्ध है। उदाहरण के लिए, मैं LINQ के बारे में बहुत अच्छी बातें सुनता हूं।

सारांश में, एसक्यूएल स्ट्रिंग्स के रूप में प्रश्नों का प्रतिनिधित्व करना आईडीई के लिए यह मुश्किल होता है कि वह लिखित और रीफैक्टरिंग प्रश्नों में सार्थक सहायता करे, वाक्यविन्यास के दोषों का पता लगाता है और संकलन समय से लेकर चलने के समय की त्रुटियों का पता लगाता है, और एसक्यूएल इंजेक्शन कमजोरियों [1] का एक महत्वपूर्ण कारण है। तो हाँ, वैध कारण हैं कि कोई सोर्स कोड में SQL स्ट्रिंग्स नहीं चाहेगा।

[१]: हाँ, तैयार कथनों का सही उपयोग SQL इंजेक्शन से भी बचाता है। लेकिन इस सूत्र में एक और जवाब एक SQL इंजेक्शन के लिए असुरक्षित था जब तक कि एक टिप्पणीकार ने यह नहीं कहा कि जूनियर प्रोग्रामर में आत्मविश्वास को प्रेरित नहीं करता है जब भी आवश्यक हो उनका सही ढंग से उपयोग ...


स्पष्ट होने के लिए: तैयार किए गए बयानों का उपयोग करना SQL इंजेक्शन को रोकता नहीं है। बाध्य चर के साथ तैयार बयान का उपयोग करता है। तैयार किए गए बयानों का उपयोग करना संभव है जो अविश्वसनीय डेटा से निर्मित होते हैं।
एंडी लेस्टर

1

यहाँ बहुत सारे शानदार जवाब। इसके अलावा जो पहले ही कहा जा चुका है, मैं एक बात और जोड़ना चाहूंगा।

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

हालांकि एक खुला दिमाग हमेशा रखें और हठधर्मिता के लिए मत गिरो। यदि आपकी दुकान एक "लाइनक" दुकान है जिसका आप उपयोग करते हैं। सिवाय इसके कि एक जगह जहां linq बिल्कुल काम नहीं करता है। (लेकिन आपको 99.9% समय नहीं चाहिए।)

तो मैं क्या करूंगा कोड बेस में कोड पर शोध करें और जांचें कि आपके सहकर्मी कैसे काम करते हैं।


+1 अच्छी बात। अधिकांश अन्य विचारों की तुलना में समर्थन अधिक महत्वपूर्ण है, इसलिए बहुत चालाक न बनें :), अगर आप एक ORM शॉप हैं, तो यह न भूलें कि ऐसे उदाहरण हैं जहां ORM उत्तर नहीं है और आपको डायरेक्ट SQL लिखने की आवश्यकता नहीं है। समय से पहले अनुकूलन न करें, लेकिन किसी भी गैर-तुच्छ अनुप्रयोग में कई बार होगा जब आपको इस मार्ग से नीचे जाना होगा।
mcottle

0

कोड डेटाबेस-इंटरेक्टिंग परत से दिखता है जो डेटाबेस और बाकी कोड के बीच है। यदि वास्तव में ऐसा है, तो यह पैटर्न-विरोधी नहीं है

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

एंटी-पैटर्न कोड के कुछ अन्य यादृच्छिक स्थान से एसक्यूएल को कॉल करना होगा। आपको डेटाबेस और बाकी कोड के बीच एक परत को परिभाषित करने की आवश्यकता है, लेकिन ऐसा नहीं है कि आपको कुछ लोकप्रिय टूल का उपयोग करना चाहिए जो वहां सहायता कर सकते हैं।


0

मेरी राय में कोई विरोधी पैटर्न नहीं है, लेकिन आप खुद को स्ट्रिंग प्रारूपण रिक्ति से निपटने के लिए पाएंगे, विशेष रूप से बड़े प्रश्नों के लिए जो एक पंक्ति में फिट नहीं हो सकते।

एक और नियम यह है कि जब कुछ शर्तों के अनुसार गतिशील प्रश्नों का निर्माण किया जाए, तो यह बहुत कठिन हो जाता है।

var query = "select * from accounts";

if(users.IsInRole('admin'))
{
   query += " join secret_balances";
}

मैं एक sql क्वेरी बिल्डर का उपयोग करने का सुझाव देता हूं


हो सकता है कि आप केवल शॉर्टहैंड का उपयोग कर रहे हों, लेकिन "सेलेक्ट *" का आँख बंद करके उपयोग करना वास्तव में बुरा विचार है क्योंकि आप उन क्षेत्रों को वापस लाएंगे जिनकी आपको ज़रूरत नहीं है (बैंडविड्थ !!) भी। हालांकि मुझे सशर्त व्यवस्थापन खंड में कोई समस्या नहीं है यह एक सशर्त "WHERE" क्लॉज के लिए बहुत फिसलन ढलान की ओर जाता है और यह एक ऐसी सड़क है जो सीधे प्रदर्शन नरक तक ले जाती है।
mcottle

0

तेजी से परिनियोजन पाइपलाइनों के साथ कई आधुनिक संगठनों के लिए जहां कोड परिवर्तन को संकलित किया जा सकता है, परीक्षण किया जा सकता है और मिनटों में उत्पादन के लिए धकेल दिया जा सकता है, यह पूरी तरह से SQL बयानों को एप्लिकेशन कोड में एम्बेड करने के लिए समझ में आता है। यह जरूरी नहीं कि आप इसके बारे में जाने के आधार पर एक प्रतिमान हैं।

संग्रहीत प्रक्रियाओं का उपयोग करने के लिए एक वैध मामला आज उन संगठनों में है जहां उत्पादन तैनाती के आसपास बहुत सारी प्रक्रिया है जिसमें क्यूए चक्र आदि शामिल हो सकते हैं। इस परिदृश्य में डीबीए टीम प्रदर्शन के मुद्दों को हल कर सकती है जो प्रारंभिक उत्पादन परिनियोजन के बाद केवल अनुकूलन द्वारा उभरती हैं। संग्रहीत प्रक्रियाओं में क्वेरी।

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


संदर्भ के लिए नीचे मूल पाठ

संग्रहीत कार्यविधियों का मुख्य लाभ यह है कि आप अपने आवेदन को फिर से जमा और पुन: वितरित किए बिना डेटाबेस प्रदर्शन को अनुकूलित कर सकते हैं।

कई संगठनों में QA चक्र आदि के बाद कोड को केवल उत्पादन के लिए धकेला जा सकता है, जिसमें दिन या सप्ताह लग सकते हैं। यदि आपका सिस्टम उपयोग के पैटर्न को बदलने या टेबल के आकार आदि में वृद्धि के कारण डेटाबेस के प्रदर्शन के मुद्दे को विकसित करता है, तो कठिन कोडित प्रश्नों के साथ समस्या को ट्रैक करना काफी मुश्किल हो सकता है, जबकि डेटाबेस में उपकरण / रिपोर्ट आदि होंगे जो समस्या संग्रहीत प्रक्रियाओं की पहचान करेंगे। । संग्रहीत प्रक्रियाओं के साथ समाधानों का उत्पादन में परीक्षण / बेंचमार्क किया जा सकता है और एप्लिकेशन सॉफ़्टवेयर के नए संस्करण को धक्का दिए बिना समस्या को जल्दी से ठीक किया जा सकता है।

यदि यह समस्या आपके सिस्टम में महत्वपूर्ण नहीं है, तो यह अनुप्रयोग में हार्ड कोड SQL कथनों के लिए पूरी तरह से वैध निर्णय है।


गलत ...........
प्रहरी

क्या आपको लगता है कि आपकी टिप्पणी किसी के लिए उपयोगी है?
bikeman868

यह सिर्फ सादा गलत है। मान लें कि हमारे पास डेटा एक्सेस के रूप में EF के साथ Web API2 प्रोजेक्ट है और भंडारण के रूप में Azure Sql। नहीं, आइए ईएफ से छुटकारा पाएं और हैंडक्राफ्टेड एसक्यूएल का उपयोग करें। डीबी स्कीमा को एसएसडीटी एसक्यूएल सर्वर प्रोजेक्ट में संग्रहित किया जाता है। डीबी स्कीमा माइग्रेशन में यह सुनिश्चित करना शामिल है कि कोडबेस को डीबी स्कीमा के लिए सिंक किया गया है और पूरी तरह से परीक्षण किया गया है, एक परीक्षण को बदलने से पहले। Azure.A कोड परिवर्तन में db में ऐप सेवा परिनियोजन स्लॉट को धकेलना शामिल है, जिसमें 2 सेकंड लगते हैं। हैंडक्राफ्टेड एसक्यूएल में प्रदर्शन प्रक्रियाएं होती हैं, जो आमतौर पर बोलती हैं, इसके विपरीत, 'ज्ञान' के बावजूद।
प्रहरी

आपके मामले में तैनाती में कुछ सेकंड लग सकते हैं, लेकिन कई लोगों के लिए ऐसा नहीं है। मैंने यह नहीं कहा कि संग्रहीत प्रक्रियाएं बेहतर हैं, बस कुछ परिस्थितियों में उनके कुछ फायदे हैं। मेरा अंतिम कथन यह है कि यदि ये परिस्थितियां लागू नहीं होती हैं तो एसक्यूएल को आवेदन में रखना बहुत ही मान्य है। यह विरोधाभास कैसे है जो आप कह रहे हैं?
bikeman868

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