2012-02-13 17 views
13

तो सी # में एक संग्रहीत प्रक्रिया मैं निम्नलिखित (कनेक्शन छोड़े गए कोड) की तरह कोड है उपयोग करने के लिए:संग्रहीत प्रक्रिया को निष्पादित करते समय, CommandType.StoredProcedure का उपयोग करके कमांड टाइप का उपयोग करने का लाभ क्या है। टेक्स्ट?

string sql = "GetClientDefaults"; 

SqlCommand cmd = new SqlCommand(sql); 
cmd.CommandType = CommandType.StoredProcedure; //<-- DO I NEED THIS?? 
cmd.Parameters.AddWithValue("@computerName", computerName); 

कहाँ एसक्यूएल एक संग्रहीत प्रक्रिया का नाम है। अब, यह कोड टिप्पणी लाइन के साथ और बिना ठीक काम करता प्रतीत होता है।

तो, क्या मुझे इस लाइन की आवश्यकता है? क्या इसे स्थापित करने के लिए कुछ प्रदर्शन (या अन्य) लाभ है? क्या इसे सेट करने या पाठ पर सेट करने का कोई लाभ नहीं है?

उत्तर

14

this blog post में परीक्षणों के मुताबिक SQL सर्वर sp_executesql में अपना कथन लपेटकर, पैरामीटरकरण करेगा, जब आप CommandType.Text का उपयोग करते हैं। लेकिन जब आप CommandType.StoredProcedure का उपयोग करते हैं तो आप इसे पैरामीटर कर देंगे और इस प्रकार डेटाबेस को कुछ काम सहेज लेंगे। बाद की विधि तेज है।

संपादित करें:

सेटअप

मैं कुछ परीक्षण अपने आप को किया जाता है और यहां गए परिणाम हैं।

इस प्रक्रिया बनाएं:

create procedure dbo.Test 
(
    @Text1 varchar(10) = 'Default1' 
    ,@Text2 varchar(10) = 'Default2' 
) 
as 
begin 
    select @Text1 as Text1, @Text2 as Text2 
end 

इसे करने के लिए एक निशान जोड़े एसक्यूएल सर्वर प्रोफाइलर का उपयोग कर।

और फिर निम्नलिखित कोड का उपयोग कर इसे कहते:

using System; 
using System.Data; 
using System.Data.SqlClient; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main() 
     { 
      CallProcedure(CommandType.Text); 
      CallProcedure(CommandType.StoredProcedure); 
     } 

     private static void CallProcedure(CommandType commandType) 
     { 
      using (SqlConnection connection = new SqlConnection("Data Source=localhost;Initial Catalog=Test;Integrated Security=SSPI;")) 
      { 
       connection.Open(); 
       using (SqlCommand textCommand = new SqlCommand("dbo.Test", connection)) 
       { 
        textCommand.CommandType = commandType; 
        textCommand.Parameters.AddWithValue("@Text1", "Text1"); 
        textCommand.Parameters.AddWithValue("@Text2", "Text2"); 
        using (IDataReader reader = textCommand.ExecuteReader()) 
        { 
         while (reader.Read()) 
         { 
          Console.WriteLine(reader["Text1"] + " " + reader["Text2"]); 
         } 
        } 
       } 
      } 
     } 
    } 
} 

परिणाम

दोनों ही मामलों कॉल आरपीसी का उपयोग किया जाता है।

यहाँ क्या पता लगाने CommandType.Text का उपयोग कर पता चलता है है:

exec sp_executesql N'dbo.Test',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2' 

और यहाँ परिणाम CommandType.StoredProcedure उपयोग कर रहा है:

exec dbo.Test @Text1=N'Text1',@Text2=N'Text2' 

आप देख सकते हैं पाठ-कॉल तो sp_executesql के लिए एक कॉल में लपेटा जाता है कि यह ठीक से पैरामीटरकृत है। यह निश्चित रूप से मामूली ओवरहेड बना देगा, और इस प्रकार मेरा पिछला बयान है कि CommandType.StoredProcedure का उपयोग करना अभी भी तेज़ है।

Msg 201, Level 16, State 4, Procedure Test, Line 0 Procedure or function 'Test' expects parameter '@Text1', which was not supplied.

इस का कारण यह है कि कैसे कॉल है:

एक और उल्लेखनीय बात यह है, और जो भी तरह का एक सौदा ब्रेकर यहाँ है, कि जब मैं मूलभूत मूल्यों के बिना प्रक्रिया बनाया मैं निम्नलिखित त्रुटि मिली है sp_executesql बनाया गया है, जैसा कि आप देख सकते हैं कि पैरामीटर घोषित किए गए हैं और आरंभ किए गए हैं, लेकिन इन्हें का उपयोग नहीं किया जाता है। काम करने के लिए कॉल के लिए, यह इस तरह से देखा जाना चाहिए था:

exec sp_executesql N'dbo.Test @Text1, @Text2',N'@Text1 nvarchar(5),@Text2 nvarchar(5)',@Text1=N'Text1',@Text2=N'Text2' 

अर्थ है, जब आप CommandType.Text आप CommandText में पैरामीटर जोड़ने जब तक आप हमेशा चाहते मूलभूत मूल्यों में इस्तेमाल किया जा करने के लिए है का उपयोग कर रहे हैं।

तो, आपके सवाल का

  1. जवाब देने के लिए उपयोग करना CommandType.StoredProcedure तेज है।
  2. आप CommandType.Text का उपयोग कर रहे हैं, तो आप जब तक आप मूलभूत मूल्यों में इस्तेमाल किया जा करना चाहते प्रक्रिया के लिए कॉल करने के लिए पैरामीटर का नाम जोड़ने की करनी होगी।
+0

- स्टोर्डप्रोसेसर का उपयोग करने से भी तेज हो सकता है? – MAW74656

+1

@ MAW74656 हां। यह भी ध्यान दें कि Panagiotis Kanavos का उत्तर है कि SQL सर्वर के अलावा अन्य प्रदाता हो सकते हैं, जो यह नहीं समझते कि आप एक proc निष्पादित करने का प्रयास कर रहे हैं जब तक कि आप इसे निर्दिष्ट न करें। –

+0

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

5

आप इसे एडीओ.NET को आपकी मदद करने के लिए अनुमति देने के लिए सेट करेंगे। जब आप CommandType.StoredProcedure का उपयोग करते हैं, तो आपको संग्रहीत प्रक्रिया नाम के बराबर CommandText रखना होगा।

उदाहरण के लिए, इस:

YourSqlCommand.CommandType = CommandType.StoredProcedure; 
YourSqlCommand.CommandText = "dbo.YourStoredProc"; 

के बराबर है:

YourSqlCommand.CommandText = "exec dbo.YourStoredProc"; 
+0

-मैं यह नहीं कह "Exec" या "dbo।" किसी भी संस्करण में और यह ठीक काम करता है। क्या इससे कोई अन्य तरीका मदद मिलेगी? – MAW74656

+0

मैं वास्तव में इसे पुन: संकलित कर दूंगा .. इसे डीबग करें और वास्तव में इसका परीक्षण करें .. क्योंकि मैंने कमांड टाइप को सेट किए बिना काम की तरह कुछ नहीं देखा है ... हमम ??? – MethodMan

+4

@ MAW74656 ऐसा इसलिए है क्योंकि SQL सर्वर में आपको 'exec' टाइप करना नहीं है यदि संग्रहित प्रो बैच का पहला कथन है। –

3

CommandType एसक्यूएल सर्वर के लिए विशिष्ट नहीं है। यह IDbCommand इंटरफ़ेस की एक संपत्ति है जो कमांडटेक्स्ट को एक विशिष्ट तरीके से इलाज करने के लिए अंतर्निहित प्रदाता को निर्देश देती है। जबकि SQL सर्वर प्रक्रियाओं के रूप में एकल-शब्द नामों का इलाज कर सकता है, आपको अन्य प्रदाताओं में काम करने की उम्मीद नहीं करनी चाहिए।

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

+0

@PagagiotisKanavos- मुझे लगता है कि आप यहां एक अलग लड़ाई लड़ रहे हैं। अधिकांश नमूना कोड ऑनलाइन SQLCommand का उपयोग करता है। लेकिन अगर मैं उस आधार को स्वीकार करता हूं, तब भी आपने यह नहीं कहा है कि कमांड टाइप करने का क्या प्रभाव है। – MAW74656

+0

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

+0

-लेकिन यह क्या सेटिंग करता है? – MAW74656

5

वहाँ वास्तव में एक बड़ा अंतर है। आप कमांड प्रकार StoredProcedure निर्दिष्ट करते हैं तो किसी भी पैरामीटर आप अपने SqlCommand में जोड़ने के लिए एक पैरामीटर प्रक्रिया कॉल जोड़ दिया जाएगा। यदि आप इसे Text के रूप में छोड़ देते हैं तो पैरामीटर को बैच में जोड़ा जाएगा, प्रक्रिया के अनुसार नहीं।

create procedure usp_test 
    @p1 char(10) = 'foo', 
    @p2 int = 42 
as 
    select @p1, @p2;  
go 

तो इस छोटे से सी # आवेदन संकलन:

static void Main(string[] args) 
    { 
     ExecWithType(CommandType.Text); 
     ExecWithType(CommandType.StoredProcedure); 
    } 

    static void ExecWithType(CommandType type) 
    { 
     using (SqlConnection conn = new SqlConnection(Settings.Default.connString)) 
     { 
      conn.Open(); 
      using (SqlCommand cmd1 = new SqlCommand("usp_test", conn)) 
      { 
       cmd1.CommandType = type; 
       cmd1.Parameters.AddWithValue("@p1", "bar"); 
       cmd1.Parameters.AddWithValue("@p2", 24); 
       using (SqlDataReader rdr = cmd1.ExecuteReader()) 
       { 
        while (rdr.Read()) 
        { 
         Console.WriteLine("Type: {0} Result: @p1: {1} @p2: {2}", type, rdr[0], rdr[1]); 
        } 
       } 
      } 
     } 
    } 

परिणाम है:

Type: Text Result: @p1: foo  @p2: 42 
Type: StoredProcedure Result: @p1: bar  @p2: 24 

आउच बिंदु को वर्णन करने के लिए, एक डमी प्रक्रिया बनाने की सुविधा देता!CommandType.Text सेटिंग के लिए हालांकि पैरामीटर बैच पर पास किए गए थे, वे प्रक्रिया पर पास नहीं हुए थे। मज़ा डिबगिंग के कई घंटे के स्रोत ...

+0

- पैरामीटर के साथ, कोई ग्रे क्षेत्र नहीं, कमांड टाइप। स्टोर्डप्रोसेडर निश्चित रूप से बेहतर, अधिक सटीक, तेज़ है। – MAW74656

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

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