Занести Image в БД

Нужно занести данные в таблицу с Image. Она расположена в pictureBox и не отправляется в бд. Возникает исключение:

Не удалось преобразовать значение параметра из Bitmap в Byte[].

private void button2_Click(object sender, EventArgs e)
{
    OpenFileDialog ofd = new OpenFileDialog();
    ofd.Filter = "Image Files(*.JPG; *.PNG)|*.JPG; *.PNG|All files (*.*)|*.*";
    if (ofd.ShowDialog() == DialogResult.OK) 
    {
        try 
        {
            pictureBox1.Image = new Bitmap(ofd.FileName);               
        }
        catch
        {
            MessageBox.Show("Невозможно открыть данный файл");
        }
    }
}

private void button1_Click(object sender, EventArgs e)
{
    myConnection = new SqlConnection(connectString);
    myConnection.Open();           

    string post = textBox1.Text;
    int sale = Convert.ToInt32(textBox2.Text);
    string ob = textBox3.Text;
    Image img = pictureBox1.Image;

    string sql1 = "INSERT INTO Vacancy(Post, Salary, Image) values(@post, @sale, @img)";
    string sql2 = "INSERT INTO Duties(Obligation) values(@ob)";

    SqlCommand command = new SqlCommand(sql1, myConnection);
    SqlCommand command2 = new SqlCommand(sql2, myConnection);
    command.Parameters.Add("@post", SqlDbType.VarChar).Value = textBox1.Text;
    command.Parameters.Add("@salet", SqlDbType.Int).Value = textBox2.Text;
    command2.Parameters.Add("@ob", SqlDbType.VarChar).Value = textBox3.Text;
    command.Parameters.Add("@img", SqlDbType.Image).Value = pictureBox1.Image;

    command.ExecuteNonQuery();
    command2.ExecuteNonQuery();
}

Ответы (1 шт):

Автор решения: Alexander Petrov

Чтобы сохранить изображение в БД, его нужно преобразовать в массив байтов. Делается это стандартно через MemoryStream.

using (var memoryStream = new MemoryStream())
{
    pictureBox1.Image.Save(memoryStream, pictureBox1.Image.RawFormat);
    command.Parameters.Add("@img", SqlDbType.Binary).Value = memoryStream.ToArray();
}

При чтении из БД нужно выполнить обратную трансформацию. Только не спрашивайте в комментариях, как это сделать! Задавайте новый отдельный вопрос при необходимости.

Обратите внимание на SqlDbType.Binary. Дело в том что тип image является устаревшим и будет удалён.
На заметку: тип image в БД совершенно не равнозначен типу Image в WinForms. Просто у них совпадают названия.


В вашем коде множество проблем. Попробую разобрать некоторые из них.

Ресурсы нужно освобождать. Для этого используйте using. Зачем? Со временем поймёте. Пока действуйте, как советую.


Давайте говорящие название всем своим переменным.
Что такое button1? Какое действие выполняет эта кнопка? Судя по коду, сохраняет данные в БД. Вот и назовите её saveButton.
Что такое textBox1? Судя по коду, из него берётся некое значение post. Вот и назовите его postTextBox.
И так далее. Пикчабоксу тоже дайте нормальное название.

Значение sale - число. Поэтому лучше использовать компонент NumericUpDown вместо TextBox.


SqlDbType.VarChar - возможно, его нужно заменить на SqlDbType.NVarChar. Потому что varchar предназначено для неюникодных символов. Если у вас допустимы русские буквы и вообще символы других алфавитов, то нужен тип nvarchar. Но я не знаю, какие именно данные у вас вводятся, поэтому смотрите сами.
В таблицах БД должны быть соответствующие типы.


Кроме того, давайте используем асинхронность. Это увеличит отзывчивость интерфейса.


Ну и последнее. У вас в коде вызываются две команды insert. Возможно, их следует обернуть в транзакцию, чтобы, если вторая не удалась, то и первая откатилась. Но я не знаю ваш сценарий использования, поэтому оставил как есть.


Вот итоговый переработанный код:

private async void saveButton_ClickAsync(object sender, EventArgs e)
{
    using (var connection = new SqlConnection(connectString))
    {
        await connection.OpenAsync();

        string sql1 = "INSERT INTO Vacancy(Post, Salary, Image) values(@post, @sale, @img)";
        string sql2 = "INSERT INTO Duties(Obligation) values(@ob)";

        using (var vacancyCommand = new SqlCommand(sql1, connection))
        using (var dutiesCommand = new SqlCommand(sql2, connection))
        {
            vacancyCommand.Parameters.Add("@post", SqlDbType.NVarChar).Value = postTextBox.Text;
            vacancyCommand.Parameters.Add("@sale", SqlDbType.Int).Value = saleNumericUpDown.Value;

            using (var memoryStream = new MemoryStream())
            {
                pictureBox1.Image.Save(memoryStream, pictureBox1.Image.RawFormat);
                vacancyCommand.Parameters.Add("@img", SqlDbType.Binary).Value = memoryStream.ToArray();
            }

            dutiesCommand.Parameters.Add("@ob", SqlDbType.NVarChar).Value = obligationTextBox.Text;

            await vacancyCommand.ExecuteNonQueryAsync();
            await dutiesCommand.ExecuteNonQueryAsync();
        }
    }
}
→ Ссылка