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 OracleDataReader
through 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();
}
.....
.....
}
}
|