2012-06-21 13 views
16

पर पास करना चाहिए, मेरे पास एक SqlDataReader है और SqlDataReader.GetBytes() विधि का उपयोग करके इसे एक varbinary (अधिकतम) कॉलम पढ़ने की आवश्यकता है। यह विधि बाइट सरणी को पॉप्युलेट करती है और इसलिए यह जानना आवश्यक है कि डेटा की लंबाई कितनी है।मुझे 'लंबाई' पैरामीटर को SqlDataReader.GetBytes()

यह वह जगह है जहां मैं भ्रमित हो जाता हूं .. स्पष्ट रूप से मैं इस पंक्ति/कॉलम में डेटाबेस से लौटाया गया सभी डेटा पढ़ना चाहता हूं, तो मुझे 'लंबाई' पैरामीटर कब पास करना चाहिए?

जहाँ तक मैं देख सकता हूं, SqlDataReader यह जानने के लिए कोई तरीका प्रदान नहीं करता है कि डेटा कितनी लंबाई उपलब्ध है, इसलिए यह विधि मेरे लिए काफी अजीब लगती है।

मैं सिर्फ int.MaxValue को पास करने और इस मुद्दे को भूलने के लिए प्रेरित हूं लेकिन इसके बारे में कुछ मेरे साथ सही नहीं बैठता है।

मुझे लगता है कि मैं बजाय कॉल कर सकते हैं

byte[] value = (byte[])dataReader["columnName"]; 

जानकारी है .. और यह पूरी तरह से आंतरिक रूप से लंबाई मुद्दे की देखभाल करने लगता है। हालांकि मैं जटिल कोड जनरेशन टेम्पलेट्स के एक सेट के साथ काम कर रहा हूं जो SqlDataReader.GetXXXX() विधियों के आसपास बनाया गया है। तो मैं GetBytes का उपयोग करने में बंधे हूं और इसके उचित उपयोग को समझने की आवश्यकता है।

+0

एसक्यूएल में एक varbinary में लंबाई के लिए पूछने के तरीके हैं - आपको इसे SQL में रखना होगा: http://msdn.microsoft.com/en-us/library/ms173486.aspx - DATALENGTH। तालिका से फ़ील्ड, डेटालेथेंथ (फ़ील्ड) का चयन करें और आप लंबाई देख सकते हैं। – TomTom

+0

धन्यवाद, मैंने SQL में DATALENGTH का उपयोग करने पर विचार किया लेकिन यह वास्तव में एक स्वीकार्य समाधान नहीं है। जैसा कि आप संभवतः डेटा एक्सेस लेयर के सभी रूपों का अनुमान लगा सकते हैं, इसलिए बुनियादी कार्यक्षमता का समर्थन करने के लिए हाथों से लिखित संग्रहित प्रक्रियाओं में इस तरह के सम्मेलनों को मजबूर करना बहुत अच्छा नहीं है। – Martyn

+0

@ मार्टिन जबकि मैं यहां हूं ... यह सुनिश्चित करने के लिए पुस्तकालय * समर्पित * हैं कि आपको कष्टप्रद ADO.NET कोड लिखने की आवश्यकता नहीं है ... "डैपर" (मेरी भारी पक्षपातपूर्ण राय में) छिपाने के लिए उत्कृष्ट है इन चिंताओं, जबकि बहुत हल्के वजन और घुसपैठ नहीं है। –

उत्तर

26

जब varbinary(max) के साथ काम कर, वहाँ दो परिदृश्य हैं:

  • डेटा की लंबाई मध्यम है
  • डेटा की लंबाई

GetBytes(), दूसरा परिदृश्य के लिए करना है जब आप CommandBehaviour.SequentialAccess उपयोग कर रहे हैं यह सुनिश्चित करें कि आप कर रहे हैं डेटा, नहीं बफरिंग यह स्ट्रीमिंग बड़ा है। विशेष रूप से, इस उपयोग में आप आमतौर पर एक लूप में स्ट्रीम में (उदाहरण के लिए) लिख रहे होंगे। उदाहरण के लिए:

// moderately sized buffer; 8040 is a SQL Server page, note 
byte[] buffer = new byte[8040]; 
long offset = 0; 
int read; 
while((read = reader.GetBytes(col, offset, buffer, 0, buffer.Length)) > 0) { 
    offset += read; 
    destination.Write(buffer, 0, read); // push downstream 
} 

हालांकि! आप मामूली आकार डेटा का उपयोग कर रहे हैं, तो फिर अपने मूल कोड:

byte[] data = (byte[])reader[col]; 

ठीक है !!। इस दृष्टिकोण के साथ कुछ भी गलत नहीं है, और वास्तव में Get* एपीआई कुछ मामलों में टूटा हुआ है - GetChar() एक उल्लेखनीय उदाहरण है (संकेत: यह काम नहीं करता है)।

यह कोई फर्क नहीं पड़ता कि आपके पास मौजूदा कोड है जो Get* का उपयोग करता है - इस मामले में, कास्ट दृष्टिकोण पूरी तरह उपयुक्त है।

+1

धन्यवाद, यह एक अच्छा जवाब है! मेरे विशेष मामले में, संपूर्ण डेटा हमेशा बाइट सरणी में पढ़ा जाएगा और किसी अन्य स्ट्रीम में buffered या धक्का नहीं दिया जाएगा। इस मामले में, क्या रीड लूप को मैन्युअल रूप से कॉल करने के लिए मैन्युअल रूप से रीड लूप लिखने के लिए कोई प्रदर्शन लाभ है और int.MaxValue लंबाई के रूप में गुजर रहा है? – Martyn

+2

@ मार्टिन 'रीडबाइट्स' स्ट्रीमिंग एपीआई है; आप ** ** कभी भी इस तरह के बड़े मूल्य को पास नहीं कर सकते हैं और मान लें कि यह सबकुछ पढ़ता है - आप ** हमेशा ** लूप की आवश्यकता होती है जब तक कि आप एक गैर-सकारात्मक मूल्य वापस न लें। मेरा मुख्य अनुमान यहां (अनचेक) है कि * आंतरिक रूप से * यह पहले से ही लंबाई (कम से कम, buffered उपयोग में) जानता है, और एक सही आकार के सरणी आवंटित करने जा रहा है और केवल डेटा को ब्लॉक-कॉपी करें। यदि आप इसे 'GetBytes()' के माध्यम से करते हैं तो आपको इसे 'मेमोरीस्ट्रीम' पर लिखना होगा और फिर अंत में 'ms.ToArray()' को कॉल करना होगा। समस्या यह है: अतिरिक्त (अनावश्यक) 'बाइट []' आवंटन। आप पर निर्भर है कि यह एक समस्या है। –

+0

हाँ, ज़ाहिर है कि आप सही हैं। लूपिंग की आवश्यकता होती है क्योंकि डेटा int.MaxValue से अधिक लंबा हो सकता है। आपकी मदद के लिए धन्यवाद - स्वीकार किया गया। – Martyn

1

आप शायद ऐसा कर सकते हैं। एमएसडीएन पर मिला। शायद यह सर्वर उद्देश्य सका

// Reset the starting byte for the new BLOB. 
    startIndex = 0; 

    // Read the bytes into outbyte[] and retain the number of bytes returned. 
    retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize); 

// Continue reading and writing while there are bytes beyond the size of the buffer. 
    while (retval == bufferSize) 
    { 
    bw.Write(outbyte); 
    bw.Flush(); 

    // Reposition the start index to the end of the last buffer and fill the buffer. 
    startIndex += bufferSize; 
    retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize); 
    } 

    // Write the remaining buffer. 
    bw.Write(outbyte, 0, (int)retval - 1); 
    bw.Flush(); 

http://msdn.microsoft.com/en-us/library/87z0hy49%28v=vs.71%29.aspx#Y132

Or this one

int ndx = rdr.GetOrdinal("<ColumnName>"); 
      if(!rdr.IsDBNull(ndx)) 
      { 
      long size = rdr.GetBytes(ndx, 0, null, 0, 0); //get the length of data 
      byte[] values = new byte[size]; 

      int bufferSize = 1024; 
      long bytesRead = 0; 
      int curPos = 0; 

      while (bytesRead < size) 
      { 
       bytesRead += rdr.GetBytes(ndx, curPos, values, curPos, bufferSize); 
       curPos += bufferSize; 
      } 
      } 
+0

वह मूल रूप से यह है। – TomTom

+1

मुझे अनुमान लगाएं - आपने इसे सीधे विधि के दस्तावेज़ से लिया है? आरटीएफएम प्रश्न;) – TomTom

+0

हां :) ट्रस्ट एमएसडीएन कोर के लिए। !! – Anand

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