| 
         Obtaining BLOB Values from a Database 
        
          The default behavior of the DataReader is to
          load incoming data as a row as soon as an entire row of data is available. Binary large
          objects (BLOBs) need to be treated differently, however, because they can contain
          gigabytes of data that cannot be contained in a single row. The
          Command.ExecuteReader method has an overload which will take a
          CommandBehavior argument to modify the default behavior of the DataReader. You can
          pass CommandBehavior.SequentialAccess to the ExecuteReader method to modify the
          default behavior of the DataReader so that instead of loading rows of data, it will load
          data sequentially as it is received. This is ideal for loading BLOBs or other large data
          structures. Note that this behavior may differ depending on your data source. 
         
        
        
          Provides a way for the DataReader to handle rows
          that contain columns with large binary values
          BLOBs. Rather than loading the entire row, SequentialAccess
          enables the DataReader to load data as a stream. When setting the DataReader to
          use SequentialAccess, it is important to note the sequence in which you access the
          fields returned. The default behavior of the DataReader, which loads an entire row as
          soon as it is available, allows you to access the fields returned in any order until the
          next row is read. When using SequentialAccess however, you must access the different
          fields returned by the DataReader in order. For example, if your query returns three
          columns, the third of which is a BLOB, you must return the values of the first and second
          fields before accessing the BLOB data in the third field. If you access the third field
          before the first or second fields, the first and second field values will no longer be
          available. This is because SequentialAccess has modified the DataReader to return data in
          sequence and the data will not be available after the DataReader has read past
          it. 
          When accessing the data in the BLOB field, use
          the GetBytes or GetChars typed accessors of the DataReader, which fill an
          array with data. You can also use GetString for character data, however to conserve
          system resources you may not want to load an entire BLOB value into a single string
          variable. You can specify a specific buffer size of data to be returned, and a starting
          location for the first byte or character to be read from the returned data. GetBytes and
          GetChars will return a long value, which represents the number of bytes or characters
          returned. If you pass a null array to GetBytes or GetChars, the long value returned
          will be the total number of bytes or characters in the BLOB. You can optionally specify
          an index in the array as a starting position for the data being read. 
         
        Writing BLOB Values to a Database 
        
          You can write a binary large object (BLOB) to a
          database as either binary or character data, depending on the type of field at your data
          source. To write a BLOB value to your database, issue the appropriate INSERT or UPDATE
          statement and pass the BLOB value as an input parameter. If your BLOB is stored as text,
          such as a SQL Server text field, you can pass the BLOB as a string parameter. If the
          BLOB is stored in binary format, such as a SQL Server image field, you can pass an array
          of type byte as a binary parameter. 
         
        Example 
        
          The following code example adds employee information to the Employees table in
          the Northwind database. A photo of the employee is read from a file and added to
          the Photo field in the table, which is an image field. The Photo field is then read using GetBytes. Notice that the employee id
          is accessed for the current row of data before the Photo, because the fields must be
          accessed sequentially. 
            
         
        using System; 
        using System.Drawing; 
        using System.Collections; 
        using System.ComponentModel; 
        using System.Windows.Forms; 
        using System.Data; 
        using System.Data.SqlClient; 
        using System.IO; 
         
        namespace Akadia.ReadWriteBlob 
        { 
            // Read and Write BLOB to/from Filesystem and
        Database 
            public class BlobSample : System.Windows.Forms.Form 
            { 
                private System.Windows.Forms.PictureBox
        pbxPhoto; 
                private System.ComponentModel.Container
        components = null; 
                private System.Windows.Forms.Button
        btnLoadPhoto; 
                private System.Windows.Forms.Button
        btnAddEmp; 
                private System.Windows.Forms.Button
        btnGetEmp; 
                private System.Windows.Forms.StatusBar
        statusBar; 
         
                // My own private
        Variables 
                private String _fname = null; 
                private SqlConnection _conn; 
         
                // Constructor 
                public BlobSample() 
                { 
                    //
        Initialize GUI 
                   
        InitializeComponent(); 
         
                    //
        Get Database Connection 
                    _conn = new
        SqlConnection("data source=XEON;"+ 
                       
        "initial catalog=Northwind;"+ 
                       
        "user id=sa;password=manager;"); 
                } 
         
                // **** Read Image from
        Filesystem and add it to the Database. 
                public void AddEmployee( 
                    string plastName, 
                    string pfirstName, 
                    string ptitle, 
                    DateTime phireDate, 
                    int preportsTo, 
                    string
        photoFilePath) 
                { 
         
                    //
        Read Image into Byte Array from Filesystem 
                    byte[] photo =
        GetPhoto(photoFilePath); 
         
                    //
        Construct INSERT Command 
                    SqlCommand addEmp = new
        SqlCommand( 
                       
        "INSERT INTO Employees ("+ 
                       
        "LastName,FirstName,Title,HireDate,ReportsTo,Photo) "+ 
                       
        "VALUES(@LastName,@FirstName,@Title,@HireDate,@ReportsTo,@Photo)",_conn); 
         
                   
        addEmp.Parameters.Add("@LastName",  SqlDbType.NVarChar, 20).Value = plastName; 
                   
        addEmp.Parameters.Add("@FirstName", SqlDbType.NVarChar, 10).Value = pfirstName; 
                   
        addEmp.Parameters.Add("@Title",     SqlDbType.NVarChar, 30).Value =
        ptitle; 
                   
        addEmp.Parameters.Add("@HireDate",  SqlDbType.DateTime).Value    
        = phireDate; 
                   
        addEmp.Parameters.Add("@ReportsTo",
        SqlDbType.Int).Value          =
        preportsTo; 
                   
        addEmp.Parameters.Add("@Photo",     SqlDbType.Image,
        photo.Length).Value = photo; 
         
                    //
        Open the Connection and INSERT the BLOB into the Database 
                    _conn.Open(); 
                   
        addEmp.ExecuteNonQuery(); 
                    _conn.Close(); 
                } 
         
                // **** Read Image into
        Byte Array from Filesystem 
                public static byte[] GetPhoto(string
        filePath) 
                { 
                    FileStream fs = new
        FileStream(filePath, FileMode.Open, FileAccess.Read); 
                    BinaryReader br = new
        BinaryReader(fs); 
         
                    byte[] photo =
        br.ReadBytes((int)fs.Length); 
         
                    br.Close(); 
                    fs.Close(); 
         
                    return photo; 
                } 
         
                // **** Read BLOB from
        the Database and save it on the Filesystem 
                public void GetEmployee(string
        plastName,string pfirstName) 
                { 
                    SqlCommand getEmp = new
        SqlCommand( 
                       
        "SELECT EmployeeID, Photo "+ 
                       
        "FROM Employees "+ 
                       
        "WHERE LastName = @lastName "+ 
                       
        "AND FirstName = @firstName", _conn); 
         
                   
        getEmp.Parameters.Add("@LastName",  SqlDbType.NVarChar, 20).Value = plastName; 
                   
        getEmp.Parameters.Add("@FirstName", SqlDbType.NVarChar, 10).Value = pfirstName; 
         
                    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 emp_id =
        "";                    
        // The employee id to use in the file name.
  
                    //
        Open the connection and read data into the DataReader. 
                    _conn.Open(); 
                    SqlDataReader myReader =
        getEmp.ExecuteReader(CommandBehavior.SequentialAccess); 
         
                    while
        (myReader.Read()) 
                    { 
                       
        // Get the employee id, which must occur before getting the
        employee. 
                       
        emp_id = myReader.GetInt32(0).ToString(); 
         
                       
        // Create a file to hold the output. 
                       
        fs = new FileStream("employee" + emp_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. 
                       
        bw.Write(outbyte, 0, (int)retval); 
                       
        bw.Flush(); 
         
                       
        // Close the output file. 
                       
        bw.Close(); 
                       
        fs.Close(); 
                    } 
         
                    //
        Close the reader and the connection. 
                    myReader.Close(); 
                    _conn.Close(); 
                } 
         
                private void btnAddEmp_Click(object sender,
        System.EventArgs e) 
                { 
                    DateTime hireDate =
        DateTime.Parse("2003.05.03"); 
                   
        AddEmployee("Mary","Jones","Software Engineer",hireDate,5,_fname); 
                    statusBar.Text =
        "Employee added to the Database"; 
                } 
         
                private void btnGetEmp_Click(object sender,
        System.EventArgs e) 
                { 
                   
        GetEmployee("Mary","Jones"); 
                    statusBar.Text =
        "Employee saved to Filesystem"; 
                } 
         
                private void btnLoadPhoto_Click(object sender,
        System.EventArgs e) 
                { 
                    OpenFileDialog dlg = new
        OpenFileDialog(); 
         
                    dlg.Title = "Open
        Photo"; 
                    dlg.Filter = "Windows
        Bitmap Files (*.bmp)|*.bmp" 
                       
        + "|All files (*.*)|*.*"; 
         
                    if (dlg.ShowDialog() ==
        DialogResult.OK) 
                    { 
                       
        try 
                       
        { 
                           
        pbxPhoto.Image = new Bitmap(dlg.OpenFile()); 
                           
        _fname = dlg.FileName; 
                       
        } 
                       
        catch (Exception ex) 
                       
        { 
                           
        MessageBox.Show("Unable to load file: " + ex.Message); 
                       
        } 
                    } 
         
                    dlg.Dispose(); 
                } 
         
                ..... 
                ..... 
         
                // The main entry point for the application. 
                [STAThread] 
                static void Main() 
                { 
                    Application.Run(new
        BlobSample()); 
                } 
            } 
        } 
       |