load picturebox image from database where image column may be null - c#

there is the code for loading image from database and shows it in picture box. the problem is if there's no pic in a row it will encounter an error however i marked as allow nulls image column in database.
private void button1_Click(object sender, EventArgs e)
{
sql = new SqlConnection(#"Data Source=PC-PC\PC;Initial Catalog=Test;Integrated Security=True");
cmd = new SqlCommand();
cmd.Connection = sql;
cmd.CommandText = ("select Image from Entry where EntryID =#EntryID");
cmd.Parameters.AddWithValue("#EntryID", Convert.ToInt32(textBox1.Text));
var da = new SqlDataAdapter(cmd);
var ds = new DataSet();
da.Fill(ds, "Images");
int count = ds.Tables["Images"].Rows.Count;
if (count > 0)
{
var data = (Byte[])(ds.Tables["Images"].Rows[count - 1]["Image"]);
var stream = new MemoryStream(data);
pictureBox1.Image= Image.FromStream(sream);
}
}

you should check for DbNull.Value.
This should do the trick:
if (count > 0)
{
if (ds.Tables["Images"].Rows[count - 1]["Image"] != DbNull.Value){
var data = (Byte[])(ds.Tables["Images"].Rows[count - 1]["Image"]);
(MemoryStreamstream = new MemoryStream(data)
pictureBox1.Image= Image.FromStream(sream);
}
}
You marked column id DB to accept null value so DB handles it but you also need do handle null in your application (you cannot cast DbNull value).
Hint
While using any kind of Stream you should use Using statement to dispose Stream after usage.

FYI, you need to learn to use using blocks. This will ensure that the objects are Disposed of in a timely manner, even if an exception is thrown:
private void button1_Click(object sender, EventArgs e)
{
var ds = new DataSet();
using (
var sql =
new SqlConnection(
#"Data Source=PC-PC\PC;Initial Catalog=Test;Integrated Security=True")
)
{
using (
var cmd = new SqlCommand
{
Connection = sql,
CommandText =
"select Image from Entry where EntryID = #EntryID"
})
{
cmd.Parameters.AddWithValue(
"#EntryID",
Convert.ToInt32(textBox1.Text));
using (var da = new SqlDataAdapter(cmd))
{
da.Fill(ds, "Images");
}
}
}
var imagesTable = ds.Tables["Images"];
var imagesRows = imagesTable.Rows;
var count = imagesRows.Count;
if (count <= 0)
return;
var imageColumnValue =
imagesRows[count - 1]["Image"];
if (imageColumnValue == DBNull.Value)
return;
var data = (Byte[]) imageColumnValue;
using (var stream = new MemoryStream(data))
{
pictureBox1.Image = Image.FromStream(stream);
}
}

just check
if(ds.Tables["Images"].Rows[count - 1]["Image"]!=DbNull.Value)
{
//you code of execution
}
else
{
//display default image
}

Related

C# Iterate through rows in a DataTable

I'm trying to Iterate through rows in a 2 column table to check 1 field in each row against a Name. Once found I want to code to assign the corresponding Number to the OurNumber variable, and break out of the loop by setting GotTheNumber to true.
Below is the code I'm using:
private void BtnDelete_Click(object sender, EventArgs e)// Sends to ConfirmDeleteEMP Form
{
ConfirmDeleteEMP form = new ConfirmDeleteEMP();
DataTable table = new DataTable();
string connstring = #"Provider = Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\HoliPlanData.accdb;Persist Security Info=False";
using (OleDbConnection conn = new OleDbConnection(connstring))
{
string query = "SELECT PayrollNo, (FirstName + ' ' + LastName) AS NAME FROM [Employee]";
OleDbDataAdapter adapter = new OleDbDataAdapter(query, conn);
adapter.Fill(table);
}
string SelectedName = DropBoxEmp.Text;
bool GotTheNumber = false;
int OurNumber = 0;
while (!GotTheNumber)
{
foreach (DataRow ThisRow in table.Rows)
{
if (SelectedName = (table.Rows[ThisRow]))
{
OurNumber = ///THATNUMBER///;
GotTheNumber = true;
}
}
}
MessageBox.Show(SelectedName);
var GoodNumber = (table.Rows[OurNumber]["PayrollNo"].ToString());
form.PassValueName = SelectedName;
form.PassSelectedPayroll = GoodNumber;
form.Tag = this;
form.Show(this);
Hide();
}
I don't know where to go from the If statement, so any help would be greatly appreciated.
Looping through the rows in your client program is exactly what you don't want to do. Let the database do that work for you. Try this:
private void BtnDelete_Click(object sender, EventArgs e)// Sends to ConfirmDeleteEMP Form
{
object result;
string query = "SELECT PayrollNo FROM [Employee] WHERE FirstName + ' ' + LastName = ?";
string connstring = #"Provider = Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\HoliPlanData.accdb;Persist Security Info=False";
using (OleDbConnection conn = new OleDbConnection(connstring))
using (OleDbCommand cmd = new OleDbCommand(query, conn))
{
//guessing at type and length here
cmd.Parameters.Add("?", OleDbType.VarWChar, 50).Value = DropBoxEmp.Text;
conn.Open();
result = cmd.ExecuteScalar();
}
if (result != null && result != DBNull.Value)
{
ConfirmDeleteEMP form = new ConfirmDeleteEMP();
form.PassValueName = DropBoxEmp.Text;
form.PassSelectedPayroll = (int)result;
form.Tag = this;
form.Show(this);
Hide();
}
}
If you really want to loop through the rows against all reason (it's slower, requires writing more code, and it's more error-prone), you can do this:
private void BtnDelete_Click(object sender, EventArgs e)// Sends to ConfirmDeleteEMP Form
{
DataTable table = new DataTable();
string query = "SELECT PayrollNo, (FirstName + ' ' + LastName) AS NAME FROM [Employee]";
string connstring = #"Provider = Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\\HoliPlanData.accdb;Persist Security Info=False";
using (OleDbConnection conn = new OleDbConnection(connstring))
{
OleDbDataAdapter adapter = new OleDbDataAdapter(query, conn);
adapter.Fill(table);
}
int PayrollNumber = 0;
foreach (DataRow ThisRow in table.Rows)
{
if (DropBoxEmp.Text == ThisRow["NAME"])
{
PayrollNumber = (int)ThisRow["PayrollNo"];
break;
}
}
//the whole loop could also be consolidated to this:
//PayrollNumber = (int)table.Rows.First(r => r["NAME"] == DropBoxEmp.Text)["PayrollNo"];
ConfirmDeleteEMP form = new ConfirmDeleteEMP();
form.PassValueName = DropBoxEmp.Text;
form.PassSelectedPayroll = PayrollNumber ;
form.Tag = this;
form.Show(this);
Hide();
}
Hm, hard to guess what exactly your problem is. But I think you just want to get the PayrollNo from the current row, aren't you?
Regarding the line further down ...
var GoodNumber = (table.Rows[OurNumber]["PayrollNo"].ToString());
... I think you could just call:
if (...)
{
OurNumber = ThisRow["PayrollNo"].ToString();
GotTheNumber = true;
}
However, I have no clue what you are doing with the following if-condition and if this really does what you want it to do:
if (SelectedName = (table.Rows[ThisRow]))
{
...
}

Database not accessed

The first one is funtion that i call. second one is the code to show the data that has already been stored in database. Now when i input the license number from the txtno and select the License number from combobox cbonumber and press the btnsearch, there is no record found message is shown even though the licensenumber and numbertype exists is database
function
public DataTable CheckExistingLicenseNo(string LicenseNumber, string Numbertype)
{
SqlConnection con = new SqlConnection("Data Source=(LocalDB)\\MSSQLLocalDB; Integrated Security=True; Initial Catalog=tprojectDB;");
string sql = "select *from tblDDDDDriver where LicenseNumber=#LicenseNumber and Numbertype=#Numbertype";
SqlCommand cmd = new SqlCommand(sql, con);
cmd.Parameters.AddWithValue("#LicenseNumber", LicenseNumber);
cmd.Parameters.AddWithValue("#Numbertype", Numbertype);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataTable db = new DataTable();
da.Fill(db);
return db; ;
}
code in btnsearch
private void btnsearch_Click(object sender, EventArgs e)
{
DataTable db = dc.CheckExistingLicenseNo(txtno.Text,cbonumbertype.Text);
if (db.Rows.Count > 0)
{
if (cbonumbertype.Text == "LicenseNumber")
{
txtlicenseno.Text = db.Rows[0]["LicenseNumber"].ToString();
txtlicensecategory.Text = db.Rows[0]["LicenseCategory"].ToString();
txtissuedate.Text = db.Rows[0]["IssueDate"].ToString();
txtrenewdate.Text = db.Rows[0]["RenewDate"].ToString();
txtfullname.Text = db.Rows[0]["FullName"].ToString();
txtdob.Text = db.Rows[0]["DOB"].ToString();
txtaddress.Text = db.Rows[0]["Address"].ToString();
string gender = db.Rows[0]["Gender"].ToString();
if (gender == "Male")
{
txtgender.Text = " MALE";
}
else
{
txtgender.Text = "FEMALE";
}
txtvehicleno.Text = db.Rows[0]["VehicleNumber"].ToString();
txthealthstaus.Text = db.Rows[0]["HealthStatus"].ToString();
txtdrivertype.Text = db.Rows[0]["DriverType"].ToString();
Image img;
byte[] bytimg = (byte[])db.Rows[0]["Image"];
//convert byte of imagedate to Image format
using (MemoryStream ms = new MemoryStream(bytimg, 0, bytimg.Length))
{
ms.Write(bytimg, 0, bytimg.Length);
img = Image.FromStream(ms, true);
pictureBox1.Image = img;
}
}
DataTable dd = dc.GetMaxDeathNo(Convert.ToDecimal(txtlicensenumber.Text));
if (dd.Rows.Count > 0)
{
txtdeathaccidentno.Text = dd.Rows[0]["DeathNumber"].ToString();
}
DataTable dM = dc.GetMaxMajorNo(Convert.ToDecimal(txtlicensenumber.Text));
if (dM.Rows.Count > 0)
{
txtmajoraccidentno.Text = dM.Rows[0]["MajorNumber"].ToString();
}
DataTable dm = dc.GetMaxMinorNo(Convert.ToDecimal(txtlicensenumber.Text));
if (dm.Rows.Count > 0)
{
txtminoraccidentno.Text = dm.Rows[0]["MinorNumber"].ToString();
}
DataTable dtrb = dc.GetTrafficRuleBroken(Convert.ToDecimal(txtlicensenumber.Text));
{
dataGridView1.DataSource = dtrb;
}
}
else
{
MessageBox.Show("No RECORD IS FOUND");
}
}
}
The only thing I suspect can be causing an issue is the value of cbonumbertype.Text. Change to cbonumbertype.SelectedValue and see if that wont help.
Change
DataTable db = dc.CheckExistingLicenseNo(txtno.Text,cbonumbertype.Text);
To
DataTable db = dc.CheckExistingLicenseNo(txtno.Text,cbonumbertype.SelectedValue);
I suspect that Bayeni's solution is the right one. You are possibly entering the ComboBox SelectedItem.Text value instead of the SelectedItem.Value value.
The easiest way to check this is to add a breakpoint to this line:
DataTable db = dc.CheckExistingLicenseNo(txtno.Text,cbonumbertype.Text);
In Visual Studio, select Debug > Start Debugging and check if the value in cbonumbertype.Text is the one that you expect to see.

Displaying Image in Imagebox when clicking on ListView row

I'm having a small problem. I want to get image data to display in an Image control from my Sql table when clicking on a ListView control row. I am using C# WPF and Microsoft SQL.
Now I can already insert the image into my database but the issue that I am having is that I can't seem to retrieve the image data once I click on a row in my ListView?
Here is the coding that I have tried...
This is the coding I use to fill the ListView:
private void FillEmployeeListView()
{
string ConString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
string CmdString = string.Empty;
using (SqlConnection CON = new SqlConnection(ConString))
{
CmdString = "SELECT EmployeeEmailAddress, EmployeePassword, EmployeeDepartment, EmployeeIDNumber, EmployeeName, EmployeeSurname, EmployeeGender, EmployeeDOB, EmployeeHomeAddress, EmployeeTelephoneNumber, EmplyeeCity, EmployeeProvinceCode, EmployeeProfilePicture FROM Main.tblEmployeeLoginDetails";
SqlCommand CMD = new SqlCommand(CmdString, CON);
SqlDataAdapter SDA = new SqlDataAdapter(CMD);
DataTable DT = new DataTable("Main.tblEmployeeLoginIDetails");
SDA.Fill(DT);
lvDisplayEmployeeInformation.ItemsSource = DT.DefaultView;
}
}
My SelectionChanged Event for my ListView:
private void lvDisplayEmployeeInformation_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
int selectedRow = lvDisplayEmployeeInformation.SelectedIndex;
if (selectedRow != -1)
{
DataView DS = (DataView)lvDisplayEmployeeInformation.ItemsSource;
string ColumnEmailAddress = DS.Table.Rows[selectedRow].ItemArray[0].ToString();
string ColumnPassword = DS.Table.Rows[selectedRow].ItemArray[1].ToString();
string ColumnDepartment = DS.Table.Rows[selectedRow].ItemArray[2].ToString();
string ColumnIDNumber = DS.Table.Rows[selectedRow].ItemArray[3].ToString();
string ColumnName = DS.Table.Rows[selectedRow].ItemArray[4].ToString();
string ColumnSurname = DS.Table.Rows[selectedRow].ItemArray[5].ToString();
string ColumnGender = DS.Table.Rows[selectedRow].ItemArray[6].ToString();
string ColumnDOB = DS.Table.Rows[selectedRow].ItemArray[7].ToString();
string ColumnHomeAddress = DS.Table.Rows[selectedRow].ItemArray[8].ToString();
string ColumnTelephoneNumber = DS.Table.Rows[selectedRow].ItemArray[9].ToString();
string ColumnCity = DS.Table.Rows[selectedRow].ItemArray[10].ToString();
string ColumnProvinceCode = DS.Table.Rows[selectedRow].ItemArray[11].ToString();
string ColumnProfilePicture = DS.Table.Rows[selectedRow].ItemArray[12].ToString();
txtEmailAddress.Text = ColumnEmailAddress;
pbPassword.Password = ColumnPassword;
txtDepartment.Text = ColumnDepartment;
txtIDNumber.Text = ColumnIDNumber;
txtName.Text = ColumnName;
txtSurname.Text = ColumnSurname;
txtGender.Text = ColumnGender;
txtDOB.Text = ColumnDOB;
txtHomeAddress.Text = ColumnHomeAddress;
txtTelephoneNumber.Text = ColumnTelephoneNumber;
txtCity.Text = ColumnCity;
txtProvinceCode.Text = ColumnProvinceCode;
imgProfilePicture.Source = _img;
And lastly this is the coding I want use to convert/insert and retrieve my image into and from my database:
private void SetImage(Binary data)
{
if (data == null)
{
imgProfilePicture.BeginInit();
imgProfilePicture.Source = null;
imgProfilePicture.EndInit();
return;
}
_img = new BitmapImage();
_img.BeginInit();
_img.StreamSource = new MemoryStream(data.ToArray());
_img.EndInit();
imgProfilePicture.BeginInit();
imgProfilePicture.Source = _img;
imgProfilePicture.EndInit();
}
private Binary GetImageBinary()
{
if (imgProfilePicture.Source == null)
return null;
Stream stream = _img.StreamSource;
Byte[] buffer = null;
if (stream != null && stream.CanRead && stream.Length > 0)
{
//Die Binary reader return 'n empty byte array :(
using (BinaryReader br = new BinaryReader(stream))
{
buffer = br.ReadBytes((int)stream.Length);
}
}
return new Binary(buffer);
}
I can already insert the text form the database to my textboxes once I click on a row in my listview. Any Ideas?
EDIT: The error I get is as follows - " No imaging component suitable to complete this operation was found."

Check varbinary type not is null and download it

I have created a table in which there is one column of type varbinary(max) to store the files.
What I want to do is that I want to show a pictureBox if that column is not null nad I have written this code:
private void ViewSentMailDet_Load(object sender, EventArgs e)
{
picturebox.Visible = false;
string con_string = #"Data Source=(local);Initial Catalog=fyp;Integrated Security=true";
SqlConnection con = new SqlConnection(con_string);
string qry = "select file from sentmail where msg_id='"+id of a particular row+"'";
SqlDataAdapter ad = new SqlDataAdapter(qry, con);
DataTable dt = new DataTable();
ad.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
if (dr["file"] != null)
picturebox.Visible = true;
}
}
But still its showing the pictureBox on load event of this page even if the file column is null.
Furthermore I want to download this particular file from the table to a disc when the user clicks on the pictureBox.
One of the major rules of using any kind of database is never return data you don't need. With this in mind you should exclude rows with no image using the query rather than checking after the fact.
So:
"select file from sentmail where msg_id='"+id of a particular row+"' and file is not null"
Rather than:
if (dr["file"] != DBNull.Value)
{
picturebox.Visible = true;
}
Giving us:
private void ViewSentMailDet_Load(object sender, EventArgs e)
{
picturebox.Visible = false;
string con_string = #"Data Source=(local);Initial Catalog=fyp;Integrated Security=true";
SqlConnection con = new SqlConnection(con_string);
string qry = "select file from sentmail where msg_id='"+id of a particular row+"' and file is not null";
SqlDataAdapter ad = new SqlDataAdapter(qry, con);
DataTable dt = new DataTable();
ad.Fill(dt);
foreach (DataRow dr in dt.Rows)
{
using (var ms = new MemoryStream((byte[])dr["file"]))
picturebox.Image = Image.FromStream(ms);
picturebox.Visible = true;
}
}
if (dr["file"] != DBNull.Value)
{
picturebox.Visible = true;
}
To check if the column contains binary data or null, you can use
if(!dr.IsNull("attach"))
{
attachment.Visible = true;
}
Get image bytes
Byte[] bytes = (Byte[])dr["attach"];
Convert image bytes to image
Image image = null;
using (var ms = new MemoryStream(bytes))
image = Image.FromStream(ms);
Show the picture on the picturebox
picturebox.Image = image;
To save the image, on picturebox.Click event handler
picturebox.Image.Save(#"drive:/path/to/save/image.bmp");
Glad to help! Please remember to accept the answer if you found it helpful.

Loading PictureBox Image From Database

i'm trying to load images from database to a PictureBox. I use these following codes in order to load them to my picture. I've written some code but don't know what I should do for continuing.
Any help will be appreciated.
private void button1_Click(object sender, EventArgs e)
{
sql = new SqlConnection(#"Data Source=PC-PC\PC;Initial Catalog=Test;Integrated Security=True");
cmd = new SqlCommand();
cmd.Connection = sql;
cmd.CommandText = ("select Image from Entry where EntryID =#EntryID");
cmd.Parameters.AddWithValue("#EntryID", Convert.ToInt32(textBox1.Text));
}
Continue with something like this in the button1_Click:
// Your code first, here.
var da = new SqlDataAdapter(cmd);
var ds = new DataSet();
da.Fill(ds, "Images");
int count = ds.Tables["Images"].Rows.Count;
if (count > 0)
{
var data = (Byte[])ds.Tables["Images"].Rows[count - 1]["Image"];
var stream = new MemoryStream(data);
pictureBox1.Image = Image.FromStream(stream);
}
Assuming we have a simple database with a table called BLOBTest:
CREATE TABLE BLOBTest
(
BLOBID INT IDENTITY NOT NULL,
BLOBData IMAGE NOT NULL
)
We could retrieve the image to code in the following way:
try
{
SqlConnection cn = new SqlConnection(strCn);
cn.Open();
//Retrieve BLOB from database into DataSet.
SqlCommand cmd = new SqlCommand("SELECT BLOBID, BLOBData FROM BLOBTest ORDER BY BLOBID", cn);
SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds, "BLOBTest");
int c = ds.Tables["BLOBTest"].Rows.Count;
if(c>0)
{ //BLOB is read into Byte array, then used to construct MemoryStream,
//then passed to PictureBox.
Byte[] byteBLOBData = new Byte[0];
byteBLOBData = (Byte[])(ds.Tables["BLOBTest"].Rows[c - 1]["BLOBData"]);
MemoryStream stmBLOBData = new MemoryStream(byteBLOBData);
pictureBox1.Image= Image.FromStream(stmBLOBData);
}
cn.Close();
}
catch(Exception ex)
{MessageBox.Show(ex.Message);}
This code retrieves the rows from the BLOBTest table in the database into a DataSet, copies the most recently added image into a Byte array and then into a MemoryStream object, and then loads the MemoryStream into the Image property of the PictureBox control.
Full reference guide:
http://support.microsoft.com/kb/317701
private void btnShowImage_Click(object sender, EventArgs e)
{
string constr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=.\\PIS(ACU).mdb;";
Con = new OleDbConnection(#constr);
Con.Open();
Com = new OleDbCommand();
Com.Connection = Con;
Com.CommandText = "SELECT Photo FROM PatientImages WHERE Patient_Id = " + val + " ";
OleDbDataReader reader = Com.ExecuteReader();
if (reader.Read())
{
byte[] picbyte = reader["Photo"] as byte[] ?? null;
if (picbyte != null)
{
MemoryStream mstream = new MemoryStream(picbyte);
pictureBoxForImage.Image = System.Drawing.Image.FromStream(mstream);
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(mstream);
}
}
HERE IS A TOTAL ANOTHER WAY TO DO SO:
You can simply convert the Image to Text before saving it into DataBase and the then convert it back to the Image after reading it:
public string ImageToStringFucntion(Image img)
{
try
{
using (MemoryStream ms = new MemoryStream())
{
img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
byte[] imgBytes = ms.ToArray();
string FinalText = Convert.ToBase64String(imgBytes, 0 , imgBytes.Length);
return FinalText;
}
}
catch
{
return null;
}
}
Now you can Insert or Update your Database...
Now Let's consider you want it back:
public Image StringToImage_(string input_)
{
try
{
byte[] imgBytes = Convert.FromBase64String(input_);
using (MemoryStream ms = new MemoryStream(imgBytes))
{
Image img = Image.FromStream(ms, true);
return img;
}
}
catch (Exception ex)
{
return null;
}
}
Now you can do as follow:
// Considering you have already pulled your data
// from database and set it in a DataSet called 'ds',
// and you picture is on the field number [1] of your DataRow
pictureBox1.Image = StringToImage_(ds.Table[0].Rows[0][1].ToString());

Categories

Resources