| Overview 
          ODP.NET offers faster and reliable access to Oracle Database by using Oracle
          Native APIs. ODP.NET provides features to access any .NET application. The data access
          through ODP.NET can be done using a collection of classes contained in
          Oracle.DataAccess assembly. DataSet is a major component of ADO.NET. It is an in-memory cache of the data
          retrieved from the database. OracleDataAdapter represents a set of data commands
          and a database connection that is used to fill the DataSet based on the query given. OracleCommand represents SQL statements to execute against datasource.
          OracleConnection is used to build the database connection. OracleDataReader is a read-only, forward-only recordset. ExecuteReader method
          of OracleCommand is used to create OracleDataReader. OracleBLOB is an OracleType specific
          to ODP.NET for accessing BLOB data from Oracle databases. Example 
          The purpose of this sample application is to demonstrate: 
            How to perform DML operations on DataSet for LOB (Large
            Objects) columns like images,sound files etc. through ODP.NET using C#.
 
How to fetch BLOB data using OracleBLOB (ODP.NET type) and OracleDataReaderthrough ODP.NET using C#
 The scenario for this sample application is to insert or update new photos for the
          employees in the "EMP" table. When this application is run, a drop down list populated
          with employee data from database is displayed. The user can select the employee for which
          he/she wishes to insert/update a photo and her/his job title. To insert/update the photo and job title
          the user can enter text for the job and select an image for the photo by clicking on 'Browse'
          button. To commit changes the user can click on 'Save' button. 
 /*********************************************************************************** This sample application shows how to perform DML operations on a DataSet for LOB
 * (Large Objects) columns like images, sound files etc. through ODP.NET using C#.
 *
 * The connection to database is made using Oracle Data Provider for .Net (ODP .Net).
 * DataSet is an in-memory cache of data that contains data filled by an
 * OracleDataAdapter.
 * An OracleDataAdapter serves as a bridge between the DataSet and the data source.
 * The connection to database is made using OracleConnection object.
 *
 * The scenario for this sample application is to insert or update new photos for
 * the employees in the "EMP" table.
 * When this application is run, a drop down list populated with employee data
 * from database is displayed. The user can select the employee for which he/she
 * wishes to insert/update a Photo and her/his Job Title.
 *
 * To insert/update the Photo and Job Title the user can enter text for
 * Job and select image for the photo by clicking on 'Browse' button.
 * To commit changes the user can click on 'Save' button.
 **********************************************************************************/
 
 // Standard Namespaces referenced in this sample application
 using System;
 using System.Drawing;
 using System.ComponentModel;
 using System.Windows.Forms;
 using System.Data;
 using System.IO;
 
 // Namespace for ODP.Net classes
 using Oracle.DataAccess.Client;
 
 // Namespace for ODP.Net Types
 using Oracle.DataAccess.Types;
 
 namespace Akadia.OraBlobs
 {
 // ManipulateOraBlobs class inherits Window's
        Form
 public class ManipulateOraBlobs : System.Windows.Forms.Form
 {
 private System.Windows.Forms.Button saveBtn;
 private System.Windows.Forms.Button
        closeBtn;
 private System.Windows.Forms.Button
        browseBtn;
 private Container components = null;
 
 // Variable for storing
        the image name, path chosen from file dialog
 private String  _strImageName = "";
 
 // To store value of
        current Employee ID
 private String _curEmpNo = "";
 
 // To store existing
        Employee Job Title
 private String _strExistText = "";
 
 // To store existing
        Employee values
 private int _empID = 0;
 private int _imageLength;
 private byte[] _imageData;
 private System.Windows.Forms.Label lblJob;
 private System.Windows.Forms.Label
        lblEmpName;
 private System.Windows.Forms.ComboBox
        cboEmpName;
 private System.Windows.Forms.TextBox
        txtEmpJob;
 private System.Windows.Forms.PictureBox
        picEmpPhoto;
 
 // For database
        connection
 private OracleConnection _conn;
 
 // Constructor
 public ManipulateOraBlobs()
 {
 //
        Creates the UI required for this application
 InitializeComponent();
 }
 
 //
        ***************************************************************
 // Entry point to this sample application
 //
        ***************************************************************
 static void Main()
 {
 //
        Instantiating this class
 ManipulateOraBlobs
        oraBlobs = new ManipulateOraBlobs();
 
 //
        Get database connection
 if
        (oraBlobs.getDBConnection())
 {
 // Populate Employee Names in the ComboBox
 oraBlobs.populateComboBox();
 
 // When this application is run, "ManipulateOraBlobs' form is
        run
 Application.Run(oraBlobs);
 }
 }
 
 //
        *******************************************************************
 // Get the database connection using the
        parameters given.
 // Note: Replace the datasource parameter with
        your datasource value
 // in ConnectionParams.cs file.
 //
        *******************************************************************
 private Boolean getDBConnection()
 {
 try
 {
 // Connection Information
 string connectionString =
 
 // Username
 "User Id=" + ConnectionParams.Username +
 
 // Password
 ";Password=" + ConnectionParams.Password +
 
 // Replace with your datasource value (TNSNames)
 ";Data Source=" + ConnectionParams.Datasource ;
 
 // Connection to datasource, using connection parameters given
        above
 _conn = new OracleConnection(connectionString);
 
 // Open database connection
 _conn.Open();
 return true;
 }
 //
        Catch exception when error in connecting to database occurs
 catch (Exception ex)
 {
 // Display error message
 MessageBox.Show(ex.ToString());
 return false;
 }
 }
 
 //
        ***********************************************************************
 // Populate Employee Names in the ComboBox with
        data from the "EMP"
 // table. 'EmpName' is displayed in the List,
        whereas the actual value
 // stored is 'EmpNo'.
 //
        ***********************************************************************
 void populateComboBox()
 {
 //
        To fill DataSet and update datasource
 OracleDataAdapter
        empAdapter;
 
 //
        In-memory cache of data
 DataSet empDataSet;
 
 //
        No selection
 // The starting position
        of text selected in the text box.
 txtEmpJob.SelectionStart
        = 0;
 
 try
 {
 // Instantiate OracleDataAdapter to create DataSet
 empAdapter = new OracleDataAdapter();
 
 // Fetch Product Details
 empAdapter.SelectCommand = new OracleCommand
 ("SELECT empno, ename FROM emp ORDER BY ename ASC",_conn);
 
 // Instantiate a DataSet object
 empDataSet = new DataSet("empDataSet");
 
 // Fill the DataSet
 empAdapter.Fill(empDataSet, "emp");
 
 // Employee Name is shown in the list displayed
 cboEmpName.DisplayMember =
        empDataSet.Tables["emp"].Columns["ename"].ToString();
 
 // Employee Id is the actual value contained in the list
 cboEmpName.ValueMember = empDataSet.Tables["emp"].Columns["empno"].ToString();
 
 // Assign DataSet as a data source for the Combo Box
 cboEmpName.DataSource = empDataSet.Tables["emp"].DefaultView;
 }
 catch(Exception ex)
 {
 // Display error message
 System.Windows.Forms.MessageBox.Show(ex.ToString());
 }
 }
 
 //
        *******************************************************************
 // This method is called on the click event of
        the 'Browse' button,
 // The purpose of this method is to display a
        File-Dialog, from
 // which the user can choose the desired photo
        for the employee.
 // The chosen image gets displayed in the
        Picture Box.
 //
        *******************************************************************
 private void browseBtn_Click(object sender,
        System.EventArgs e)
 {
 try
 {
 // Instantiate File Dialog box
 FileDialog fileDlg = new OpenFileDialog();
 
 // Set the initial directory
 fileDlg.InitialDirectory =
 "E:\\MyDotNet\\MyWinFormsTutorial\\OraEmpWithBlob\\doc\\images" ;
 
 // Filter image(.jpg, .bmp, .gif) files only
 fileDlg.Filter = "Image File (*.jpg;*.bmp;*.gif)|*.jpg;*.bmp;*.gif";
 
 // Restores the current directory before closing
 fileDlg.RestoreDirectory = true ;
 
 // When file is selected from the File Dialog
 if(fileDlg.ShowDialog() == DialogResult.OK)
 {
 // Store the name of selected file into a variable
 _strImageName = fileDlg.FileName;
 
 // Create a bitmap for selected image
 Bitmap newImage= new Bitmap(_strImageName);
 
 // Fit the image to the size of picture box
 picEmpPhoto.SizeMode = PictureBoxSizeMode.StretchImage;
 
 // Show the bitmap in picture box
 picEmpPhoto.Image = (Image)newImage;
 }
 
 // No Image chosen
 fileDlg = null;
 }
 catch(System.ArgumentException ex)
 {
 // Display error message, if image is invalid
 _strImageName = "";
 System.Windows.Forms.MessageBox.Show(ex.ToString());
 }
 catch(Exception ex)
 {
 // Display error message
 System.Windows.Forms.MessageBox.Show(ex.ToString());
 }
 }
 
 //
        *******************************************************************************
 // This method is called on the click event of
        the 'Save' button,
 // It calls "updateData" method for data
        updation of Job and Photos.
 //
        *******************************************************************************
 private void saveBtn_Click(object sender,
        System.EventArgs e)
 {
 this.updateData();
 }
 
 //
        *****************************************************************************
 // This method is called from the click event of
        Save button and
 // SelectedIndexChanged event of Products
        DropDown list.
 //
 // The purpose of this method is to demonstrate
        DML operations on a Data Set for
 // LOB(Large Object)data. The functionalitity of
        this method is to insert
 // a new employee photo or update an existing
        one.
 //
 // The flow of this method is as follows:
 // 1. Instantiate an OracleDataAdapter object
        with the query for 'emp'
 //    table.
 // 2. Configure the schema to match with Data
        Source. Set Primary Key information.
 // 3. OracleCommandBuilder automatically
        generates the command for loading data
 //    for the given query.
 // 4. The Dataset is filled with data that is
        loaded through OracleDataAdapter.
 // 5. Create a DataRow in a DataTable contained
        in the DataSet for a new
 //    photo or find the current
        DataRow for the existing photo.
 // 6. Convert new the photo image into a byte
        array.
 // 7. Assign the corresponding values to the
        columns in the Data Row.
 // 8. Add the Data Row to the Data Set for a new
        photo or end the edit
 //    operation for existing
        photo.
 // 9. Update the database with the Data Set
        values. Hence adding/updating
 //    'emp' table data.
 //
        *************************************************************************
 private void updateData()
 {
 try
 {
 // Check if Image or Text is changed.
 if (_strImageName != "" || _strExistText != txtEmpJob.Text)
 {
 // Change the default cursor to 'WaitCursor'(an HourGlass)
 this.Cursor = Cursors.WaitCursor;
 
 // Change the default cursor to 'WaitCursor'(an HourGlass)
 this.Cursor = Cursors.WaitCursor;
 
 // To fill Dataset and update datasource
 OracleDataAdapter empAdapter;
 
 // In-memory cache of data
 DataSet empDataSet;
 
 // Data Row contained in Data Table
 DataRow empRow;
 
 // FileStream to get the Employee Photo
 FileStream fs;
 
 // Get Image Data from the Filesystem if User has loaded a Photo
 // by the 'Browse' button
 if (_strImageName != "")
 {
 fs = new FileStream(@_strImageName, FileMode.Open,FileAccess.Read);
 _imageLength = (int)fs.Length;
 
 // Create a byte array of file stream length
 _imageData = new byte[fs.Length];
 
 // Read block of bytes from stream into the byte array
 fs.Read(_imageData,0,System.Convert.ToInt32(fs.Length));
 
 // Close the File Stream
 fs.Close();
 }
 
 // Instantiate an OracleDataAdapter object with the
 // appropriate query
 empAdapter = new OracleDataAdapter(
 "SELECT empno, ename, job, photo" +
 "  FROM emp WHERE empno = " + _curEmpNo, _conn);
 
 // Instantiate a DataSet object
 empDataSet= new DataSet("emp");
 
 // Create an UPDATE command as a template for the
 // OracleDataAdapter.
 empAdapter.UpdateCommand = new OracleCommand
 ("UPDATE emp SET " +
 "job = :iJOB, "+
 "photo = :iPHOTO " +
 "WHERE empno = :iEMPNO", _conn);
 
 // Add the Parameters for the UPDATE Command
 empAdapter.UpdateCommand.Parameters.Add(":iJOB",
 OracleDbType.Varchar2, 9, "job");
 empAdapter.UpdateCommand.Parameters.Add(":iPHOTO",
 OracleDbType.Blob, _imageLength, "photo");
 empAdapter.UpdateCommand.Parameters.Add(":iEMPNO",
 OracleDbType.Int16, 0, "empno");
 
 // Configure the schema to match with the Data Source.
 // AddWithKey sets the Primary Key information to complete the
 // schema information
 empAdapter.MissingSchemaAction = MissingSchemaAction.AddWithKey;
 
 // Configures the schema to match with Data Source
 empAdapter.FillSchema(empDataSet, SchemaType.Source, "emp");
 
 // Fills the DataSet with 'EMP' table data
 empAdapter.Fill(empDataSet,"emp");
 
 // Get the current Employee ID row for updation
 DataTable empTable = empDataSet.Tables["emp"];
 empRow = empTable.Rows.Find(_curEmpNo);
 
 // Start the edit operation on the current row in
 // the 'emp' table within the dataset.
 empRow.BeginEdit();
 
 // Assign the value of the Job Title
 empRow["job"] = txtEmpJob.Text;
 
 // Assign the value of the Photo if not empty
 if (_imageData.Length != 0)
 {
 empRow["photo"] = _imageData;
 }
 
 // End the editing current row operation
 empRow.EndEdit();
 
 // Update the database table 'EMP'
 empAdapter.Update(empDataSet,"emp");
 
 // Reset variables
 _strImageName = "";
 _strExistText = txtEmpJob.Text;
 
 // Set the wait cursor to default cursor
 this.Cursor = Cursors.Default;
 
 // Display message on successful data updatation
 MessageBox.Show("Data saved successfully");
 }
 else
 {
 MessageBox.Show("Select Photo or change Job Title for the Employee");
 }
 }
 catch(Exception ex)
 {
 System.Windows.Forms.MessageBox.Show(ex.ToString());
 }
 }
 
 //
        ***********************************************************************
 // This method is called when an Item is
        selected from 'cboEmpName'
 // drop down list. The purpose of this method is
        to demonstrate how to
 // fetch BLOB lob as an OracleLOB (ODP .Net Data
        Type) using an
 // OracleDataReader.
 // The flow of the method is as follows:
 // 1. Clear the contents of Job-Title and
        Photo.
 // 2. Populate OracleDataReader with data from
        'EMP' table, through
 //    ExecuteReader method of
        OracleCommand object. The data is fetched
 //    based on the Emplyoyy
        selected from 'cboEmpName' list.
 // 3. Assign value for Job-Title from the
        OracleDataReader.
 // 4. The Image(BLOB) is read into a Byte array,
        then used to construct
 //    MemoryStream and passed to
        PictureBox.
 //
        ***********************************************************************
 private void
        cboEmpName_SelectedIndexChanged(object sender, System.EventArgs e)
 {
 //
        For fetching read only rows from datasource
 OracleDataReader
        oraImgReader;
 
 //
        For executing SQL statements against datasource
 OracleCommand
        oraImgCmd;
 
 //
        To store MessageBox result
 DialogResult x;
 
 //
        If Image orText is changed then promt user to save.
 if (_strImageName != ""
        || _strExistText != txtEmpJob.Text)
 {
 // MessageBox prompting user whether he/she wishes to save changes
        made
 x = MessageBox.Show("Do you want to save changes ?",
 "Save Dialog",MessageBoxButtons.YesNo);
 
 // If the user wishes to save changes
 if (x == DialogResult.Yes)
 {
 // Call the method for insertion or updation
 updateData();
 
 // Reset variable
 _empID =  int.Parse(cboEmpName.GetItemText(cboEmpName.SelectedValue));
 }
 
 // If the user doesn't wish to save changes
 else
 {
 // Reset variables
 _strImageName ="";
 _empID =  int.Parse(cboEmpName.GetItemText(cboEmpName.SelectedValue));
 }
 }
 try
 {
 // Initializing, clear contents
 txtEmpJob.Text ="";
 picEmpPhoto.Image = null;
 _strImageName = "";
 _curEmpNo ="";
 _strExistText="";
 
 // Fetch Product Details using OracleCommand
 // for the selected Product from the Combobox
 string strSelectedId = cboEmpName.GetItemText(cboEmpName.SelectedValue);
 oraImgCmd = new OracleCommand(
 "SELECT " +
 "empno, " +
 "job, " +
 "photo  " +
 "FROM emp " +
 "WHERE empno = " + strSelectedId ,_conn);
 
 // Set OracleConnection for this instance of OracleCommand
 oraImgCmd.Connection = _conn;
 
 // Set Command type as text
 oraImgCmd.CommandType = CommandType.Text;
 
 // Sends the CommandText to the Connection
 // and builds an OracleDataReader
 oraImgReader = oraImgCmd.ExecuteReader();
 
 // Read data
 // Returns true if another row exists; otherwise, returns false.
 Boolean recordExist = oraImgReader.Read();
 
 // If data exists
 if (recordExist)
 {
 // Store current Employee value
 if (!oraImgReader.IsDBNull(0))
 {
 _curEmpNo = oraImgReader.GetInt32(0).ToString();
 }
 
 // Assign Job-Title to the Text Box
 if (oraImgReader.GetValue(1).ToString() != "")
 {
 _strExistText =  oraImgReader.GetString(1);
 txtEmpJob.Text = _strExistText;
 }
 
 // If Photo exists in the Database, load it into the
        PictureBox
 if (oraImgReader.GetValue(2).ToString() != "")
 {
 // Fetch the BLOB data through OracleDataReader using OracleBlob
        type
 OracleBlob blob = oraImgReader.GetOracleBlob(2);
 
 // Create a byte array of the size of the Blob obtained
 Byte[] byteArr =  new Byte[blob.Length];
 
 // Read blob data into byte array
 int i = blob.Read(byteArr,0,System.Convert.ToInt32(blob.Length));
 
 // Get the primitive byte data into in-memory data stream
 MemoryStream memStream = new MemoryStream(byteArr);
 
 // Attach the in-memory data stream to the PictureBox
 picEmpPhoto.Image = Image.FromStream(memStream);
 
 // Fit the image to the PictureBox size
 picEmpPhoto.SizeMode = PictureBoxSizeMode.StretchImage;
 }
 // close the OracleDataReader
 oraImgReader.Close();
 }
 
 // Reset  variable
 _empID =  int.Parse(cboEmpName.GetItemText(cboEmpName.SelectedValue));
 }
 
 //
        Catch exception when accessing arrary element out of bound
 catch
        (System.IndexOutOfRangeException rangeException)
 {
 // Do nothing
 rangeException.ToString();
 }
 catch (Exception ex)
 {
 // Display error message
 System.Windows.Forms.MessageBox.Show( ex.ToString());
 }
 }
 
 //
        **********************************************************************
 // This method is called on the click event of
        the 'Close' button.
 // The purpose of this method is to close the
        database connection,
 // the form 'ManipulateOraBlobs' and then exit
        out of the application.
 //
        **********************************************************************
 private void closeBtn_Click(object sender,
        System.EventArgs e)
 {
 _conn.Close();
 this.Close();
 Application.Exit();
 }
 .....
 .....
 }
 }
 |