Click here to Skip to main content
15,938,446 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Good day,

I am trying to save an image to a sql database and the retrieve it again to display in a picture box. I am not receiving any errors when storing the image, but when I try to retrieve it and display it in the picturebox I get "Paramater not valid." exception. Please help me find what I am missing.

My code to store the image:

C#
private void btnSave_Click(object sender, EventArgs e)
        {
            _gymViewModel.SaveGymDetailsToDatabase(txtGymName.Text, txtOwnerName.Text, txtAddress1.Text, 
                                                   txtAddress2.Text, txtAddress3.Text, txtPrNo.Text, 
                                                   txtTel.Text, txtFax.Text, picLogo.Image);
        }


ViewModel:

C#
GymManagementService gymManagementService = new GymManagementService();

        public List<GymInformation> Information = new List<GymInformation>();

        public void SaveGymDetailsToDatabase(string gymName, string gymOwner, string gymAddress, 
                                             string gymTown, string gymZip, string gymPrac, 
                                             string gymTel, string gymFax, Image gymLogo)
        {
            gymManagementService.SaveGymDetailsToDatabase(gymName, gymOwner, gymAddress, gymTown, gymZip, gymPrac, gymTel, gymFax, gymLogo);
        }


Connect to database:

C#
public void SaveGymDetailsToDatabase(string gymName, string gymOwner, string gymAddress, string gymTown,
                                             string gymZip, string gymPrac, string gymTel,
                                             string gymFax, Image gymLogo)
        {
            using (SqlConnection Conn = new SqlConnection(Connect.sConnStr))
            {
                try
                {
                    Conn.Open();
                    Byte[] imgData = null;

                    using (MemoryStream stream = new MemoryStream())
                    {
                        gymLogo.Save(stream, ImageFormat.Jpeg);
                        imgData = stream.ToArray();
                    }

                    string sSql = @"INSERT INTO gym_information(gym_name, gym_owner, gym_address_street, gym_address_town, gym_address_zip,
                                                                gym_prac_number, gym_telephone, gym_fax, gym_logo) 
                                    VALUES('" + gymName + "', '" + gymOwner + "', '" + gymAddress + "', '" + gymTown + "', '" + gymZip +
                                           "', '" + gymPrac + "', '" + gymTel + "', '" + gymFax + "', '" + imgData + "');";
                    int iReturn = Connect.getDataCommand(sSql, Conn).ExecuteNonQuery();
                }
                catch
                {

                }
                finally
                {
                    Conn.Close();
                    Conn.Dispose();
                }
            }
        }



Now I try to retrieve and save in picture box.

Code:

C#
 private void EditGymInformation_Load(object sender, EventArgs e)
        {
_gymViewModel.RetrieveGymDetailsFromDatabase();
            if (_gymViewModel.CheckIfGymInformationExists() == true)
            {
                txtGymName.Text = _gymViewModel.Information[0].GymName.ToString();
                txtOwnerName.Text = _gymViewModel.Information[0].GymOwner.ToString();
                txtAddress1.Text = _gymViewModel.Information[0].GymAddress.ToString();
                txtAddress2.Text = _gymViewModel.Information[0].GymTown.ToString();
                txtAddress3.Text = _gymViewModel.Information[0].GymZip.ToString();
                txtTel.Text = _gymViewModel.Information[0].Tel.ToString();
                txtFax.Text = _gymViewModel.Information[0].Fax.ToString();
                txtPrNo.Text = _gymViewModel.Information[0].PrNumber.ToString();
                picLogo.Image = Image.FromStream(new System.IO.MemoryStream(_gymViewModel.Information[0].GymLogo));
            }
        }


ViewModel:

C#
public void RetrieveGymDetailsFromDatabase()
        {
            Information = gymManagementService.RetrieveInformationFromDatabase();
        }


Connect to database:

C#
public List<GymInformation> RetrieveInformationFromDatabase()
        {
            using (SqlConnection Conn = new SqlConnection(Connect.sConnStr))
            {
                try
                {
                    Conn.Open();
                    var gym_information = new List<GymInformation>();

                    string sSql = "SELECT * FROM gym_information";

                    SqlDataReader reader = Connect.getDataCommand(sSql, Conn).ExecuteReader();

                    while (reader.Read())
                    {
                         var information = new GymInformation()
                         {
                            Id = Convert.ToInt32(reader["gym_id"]),
                            GymName = reader["gym_name"].ToString(),
                            GymOwner = reader["gym_owner"].ToString(),
                            GymAddress = reader["gym_address_street"].ToString(),
                            GymTown = reader["gym_address_town"].ToString(),
                            GymZip = reader["gym_address_zip"].ToString(),
                            Tel = reader["gym_telephone"].ToString(),
                            Fax = reader["gym_fax"].ToString(),
                            PrNumber = reader["gym_prac_number"].ToString(),
                            GymLogo = (byte[])reader["gym_logo"]
                    };
                        gym_information.Add(information);
                    }
                    return gym_information;
                }
                catch (Exception ex)
                {
                    _errorViewModel.RecordAnError(ex, "Error");
                    return null;
                }
                finally
                {
                    Conn.Close();
                    Conn.Dispose();
                }
            }
        }


What am I missing? Please help!
Posted

1 solution

Your code is vulnerable to SQL Injection[^]. NEVER use string concatenation to build a SQL query. ALWAYS use a parameterized query.

Using a properly parameterized query will also fix your problem. Currently, your gym_logo column contains the literal string "System.Byte[]", since you're calling ToString() on the byte array.

C#
public void SaveGymDetailsToDatabase(
    string gymName, string gymOwner, string gymAddress, string gymTown,
    string gymZip, string gymPrac, string gymTel,
    string gymFax, Image gymLogo)
{
    const string CommandText = @"INSERT INTO gym_information (gym_name, gym_owner, gym_address_street, gym_address_town, gym_address_zip, gym_prac_number, gym_telephone, gym_fax, gym_logo) "
        + @"VALUES (@gym_name, @gym_owner, @gym_address_street, @gym_address_town, @gym_address_zip, @gym_prac_number, @gym_telephone, @gym_fax, @gym_logo)";
    
    byte[] imageData;
    if (gymLogo == null)
    {
        imageData = null;
    }
    else
    {
        using (MemoryStream stream = new MemoryStream())
        {
            gymLogo.Save(stream, ImageFormat.Jpeg);
            imageData = stream.ToArray();
        }
    }
    
    using (SqlConnection connection = new SqlConnection(Connect.sConnStr))
    using (SqlCommand command = new SqlCommand(CommandText, connection))
    {
        command.Parameters.AddWithValue("@gym_name", gymName);
        command.Parameters.AddWithValue("@gym_owner", gymOwner);
        command.Parameters.AddWithValue("@gym_address_street", gymAddress);
        command.Parameters.AddWithValue("@gym_address_town", gymTown);
        command.Parameters.AddWithValue("@gym_address_zip", gymZip);
        command.Parameters.AddWithValue("@gym_prac_number", gymPrac);
        command.Parameters.AddWithValue("@gym_telephone", gymTel);
        command.Parameters.AddWithValue("@gym_fax", gymFax);
        command.Parameters.AddWithValue("@gym_logo", imageData);
        
        connection.Open();
        command.ExecuteNonQuery();
    }
}



Everything you wanted to know about SQL injection (but were afraid to ask) | Troy Hunt[^]
How can I explain SQL injection without technical jargon? | Information Security Stack Exchange[^]
Query Parameterization Cheat Sheet | OWASP[^]
SQL injection attack mechanics | Pluralsight [^]
 
Share this answer
 
Comments
Christopher Smit 1-Dec-15 12:38pm    
Okay your solution sorted out the exception, so I will accept the solution. However when I try to display the image again the picturebox just shows a blank white image. Do I also maybe have an error in my code there? Sorry this is my first time working with images in databases. I usually only saved paths to image files and displayed them... lol
Richard Deeming 1-Dec-15 12:46pm    
Nothing obviously wrong. Have you checked the value of the gym_logo field in the first row of the table? For a valid JPEG image, it should start with: 0xFF 0xD8 0xFF.
Christopher Smit 1-Dec-15 13:30pm    
The value does start with 0xFF........
Richard Deeming 1-Dec-15 13:32pm    
So it sounds like the first row in the table has a completely blank image.

NB: Based on the code you've posted, you're inserting new rows, but you only ever display the first row. Could that be the problem?
Christopher Smit 1-Dec-15 13:34pm    
The program is suppose to only read one row. There cannot be more than one row of details for the specific gym. Could this pose a problem when it comes to the image?

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900