2011-03-20 12 views
33

का उपयोग कर बाइनरी डेटा प्राप्त करना मेरे पास ब्लॉब (आईडी (int), डेटा (छवि) नामक एक तालिका है। मुझे उस छवि डेटा को प्राप्त करने के लिए SqlDataReader का उपयोग करने की आवश्यकता है। ध्यान दें कि मैं प्रतिक्रिया नहीं करना चाहता हूं। ब्राउज़र को डेटा प्रिंट करें()। मुझे बस उस बाइनरी डेटा को बाइट [] के रूप में कुछ आंतरिक परिचालनों के लिए उपयोग करने की आवश्यकता है। एकमात्र तरीका जिसे मैं सोच सकता हूं, एसक्लडाटा रीडर का उपयोग कर आईडी प्राप्त कर रहा है और फिर किसी दिए गए आईडी के लिए बाइट [] के रूप में प्राप्त करने के लिए SqlCommand.ExecuteScalar() का उपयोग करें। क्या मैं उस छवि डेटा को बाइट [] के रूप में प्राप्त करने के लिए केवल SqlDataReader (SqlCommand.ExecuteReader) का उपयोग कर सकता हूं? क्या मुझे कुछ याद आ रही है?SqlDataReader

उत्तर

57

आपको इसे (byte[])reader.Items["Data"] के माध्यम से प्राप्त करने में सक्षम होना चाहिए।

यह भी ध्यान रखें कि image डेटा प्रकार बहिष्कृत है, और SQL सर्वर के भविष्य के संस्करण में हटा दिया जाएगा; इसके बजाय varbinary(max) का उपयोग करें।

+17

यहां तक ​​कि छोटा: '(बाइट []) पाठक [" डेटा "]' – Cosmin

+2

मुझे .NET 4.0 में 'SqlDataReader' पर 'आइटम' संग्रह भी नहीं दिखाई देता है। – Zack

+0

क्या आइटम संग्रह बहिष्कृत है? –

16

हां, आप SqlDataReader.GetBytes का उपयोग कर सकते हैं। आप पहले कॉल में बफर के लिए null में पास करना चाहते हैं, यह पता लगाने के लिए कि कितना डेटा है, और फिर इसे उचित आकार के बफर के साथ फिर से कॉल करें।

आप बस सूचकांक का उपयोग करने और परिणाम को बाइट सरणी में डालने में सक्षम हो सकते हैं - मुझे यकीन नहीं है। एक कोशिश के लायक :)

+1

इंडस्ट्रीज़ NDX = rdr.GetOrdinal (""); अगर (! Rdr.IsDBNull (ndx)) { लंबा आकार = rdr.GetBytes (ndx, 0, null, 0, 0); // डेटा की लंबाई बाइट [] मान = नया बाइट [आकार] प्राप्त करें; int bufferSize = 1024; लंबे बाइट्स पढ़ें = 0; int curPos = 0; जबकि (बाइट्स रीड <आकार) { बाइट्स रीड + = rdr.GetBytes (ndx, curPos, मान, curPos, bufferSize); curPos + = बफर आकार; } } –

+0

@ydobonmai: जब आपके पास पहले से सही आकार का बफर होता है तो एक अलग बफर आकार से परेशान क्यों होता है? और आपको 'curPos' के बजाय' बाइट्स रीड 'का उपयोग करना चाहिए; आप वर्तमान में हमेशा यह मानते हैं कि यह एक पूर्ण बफर राशि पढ़ता है। –

+0

SqlDataReader.GetBytes() एक बहुत ही कुशल विधि की तरह लगता है क्योंकि आप उसी सरणी का पुन: उपयोग कर सकते हैं (यदि इसका उचित आकार है)। इसलिए आप प्रत्येक कॉलम के लिए एक नया सरणी नहीं बनाते हैं (बाइट []) पाठक ["डेटा"] करेगा। – mmmmmmmm

7

MSDN से। यकीन नहीं है कि मैं इससे पहले क्यों नहीं मिला।

SqlConnection pubsConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=pubs;"); 
    SqlCommand logoCMD = new SqlCommand("SELECT pub_id, logo FROM pub_info", pubsConn); 

    FileStream fs;       // Writes the BLOB to a file (*.bmp). 
    BinaryWriter bw;      // Streams the BLOB to the FileStream object. 

    int bufferSize = 100;     // Size of the BLOB buffer. 
    byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes. 
    long retval;       // The bytes returned from GetBytes. 
    long startIndex = 0;     // The starting position in the BLOB output. 

    string pub_id = "";      // The publisher id to use in the file name. 

    // Open the connection and read data into the DataReader. 
    pubsConn.Open(); 
    SqlDataReader myReader = logoCMD.ExecuteReader(CommandBehavior.SequentialAccess); 

    while (myReader.Read()) 
    { 
     // Get the publisher id, which must occur before getting the logo. 
     pub_id = myReader.GetString(0); 

     // Create a file to hold the output. 
     fs = new FileStream("logo" + pub_id + ".bmp", FileMode.OpenOrCreate, FileAccess.Write); 
     bw = new BinaryWriter(fs); 

     // 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. 
     if(retval > 0) // if file size can divide to buffer size 
      bw.Write(outbyte, 0, (int)retval); //original MSDN source had retval-1, a bug 
     bw.Flush(); 

     // Close the output file. 
     bw.Close(); 
     fs.Close(); 
    } 

    // Close the reader and the connection. 
    myReader.Close(); 
    pubsConn.Close(); 
+4

इस पर एक नोट: यदि आप CommandBehavior सेट नहीं करते हैं।ExecuteReader कॉल पर अनुक्रमिक पहुंच (उदाहरण के लिए डेटा परत के किसी अन्य भाग से पाठक प्राप्त करना), यह आपकी याददाश्त के लिए भयानक चीजें करेगा (गेटबाइट्स() को प्रत्येक कॉल के लिए ब्लॉब-साइज्ड बाइट सरणी बनाना); इस समाधान का उपयोग केवल कमांडबिहियर के साथ किया जाना चाहिए। आवश्यक प्रदर्शन जैसा कि यहां प्रदर्शित किया गया है। – Tao

+1

कोई भी बफर आकार पर निर्णय लेने के तरीके पर टिप्पणियां प्रदान कर सकता है? उदाहरण 100 का उपयोग करता है, लेकिन 10 क्यों नहीं और 10,000 क्यों नहीं? ऐसे कारक क्या हैं जिन पर विचार करने की आवश्यकता है? –

1

पाठक का उपयोग करने की कोई आवश्यकता नहीं है। डेटाबेस से मान लाने के लिए बस डेटासेट का उपयोग करें (संग्रहीत प्रो या किसी अन्य विधि का उपयोग करके) और बस इसे बाइट (नीचे कोड) के साथ डालें और उसे बाइट सरणी में संग्रहीत करें। आपका काम पूरा हो गया है

byte[] productImage; 
productImage = (byte[])ds.Tables[0].Rows[0]["Image"]; 
9

.NET फ्रेमवर्क 4.5 में आप स्ट्रीम के रूप में द्विआधारी डेटा का उपयोग करने GetStream विधि का उपयोग कर सकते हैं।

0

उपयोग सुरक्षित और लचीला बाइट्स पढ़ने के लिए इस समारोह:

/// <summary> 
    /// Reads all available bytes from reader 
    /// </summary> 
    /// <param name="reader"></param> 
    /// <param name="ordinal"></param> 
    /// <returns></returns> 
    private byte[] GetBytes(SqliteDataReader reader, int ordinal) 
    { 
     byte[] result = null; 

     if (!reader.IsDBNull(ordinal)) 
     { 
      long size = reader.GetBytes(ordinal, 0, null, 0, 0); //get the length of data 
      result = new byte[size]; 
      int bufferSize = 1024; 
      long bytesRead = 0; 
      int curPos = 0; 
      while (bytesRead < size) 
      { 
       bytesRead += reader.GetBytes(ordinal, curPos, result, curPos, bufferSize); 
       curPos += bufferSize; 
      } 
     } 

     return result; 
    } 
संबंधित मुद्दे