Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Базы данных под .NET > Переходы по БД которая содержит картинки


Автор: Redstuff 21.8.2007, 23:00
Столкнулся с проблемой перехода к записи в таблице, которая содержит картинки.
Есть таблица, но не во всех записях содержится картинка и возникает следующая ошибка:
(8 строка)
Код

Не удалось привести тип объекта "System.DBNull" к типу "System.Byte[]".

Участок кода:
Код

this.BindingContext[ds, "Hardware"].Position += 1;
HardwareInfo();
SqlCommand cmdSelect = new SqlCommand("select Photo from Hardware where ID=@ID", con);
cmdSelect.Parameters.Add("@ID", SqlDbType.Int, 4);
сmdSelect.Parameters["@ID"].Value = txtID.Text;
con.Open();

byte[] barrImg = (byte[])cmdSelect.ExecuteScalar();
string strfn = Convert.ToString(DateTime.Now.ToFileTime());
FileStream fs = new FileStream(strfn, FileMode.CreateNew, FileAccess.Write);
fs.Write(barrImg, 0, barrImg.Length);
fs.Flush();
fs.Close();

Bitmap bmp = new Bitmap(strfn);
pictureBox1.BackgroundImage = bmp;
pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;

ShowPosition();
con.Close();

Как можно решить проблему? Хотелось бы получать в pictureBox1 текстовую надпись "картинка отсутствует" (без применения картинок хранящихся в бд) или вовсе пустой pictureBox1.

На ум приходит лишь одна мысль, загружать картинки с надписью "картинка отсутствует", но может есть лучше решение?

Автор: Idsa 22.8.2007, 08:10
Изменяем код :
Код

object barrImgObj = cmdSelect.ExecuteScalar(); //это до 8-й строчки
if (barrImgObj != null)
{
 byte[] barrImg = (byte[])barrImgObj; //это вместо строки 8
// здесь весь код для обработки картинки; похоже, что до 19 строчки включительно
}
con.Close();

Автор: Redstuff 22.8.2007, 10:19
Idsa, а в запросе не надо ничего менять? Потому как 
Код

if (barrImgObj != null)

это условие выполняется всегда... И ошибка на строку 
Код

byte[] barrImg = (byte[])barrImgObj;

Автор: Idsa 22.8.2007, 11:24
Цитата(Redstuff @  21.8.2007,  23:00 Найти цитируемый пост)
Есть таблица, но не во всех записях содержится картинка и возникает следующая ошибка:

Хм... А те строки, в которых нет фоток, - пустые?
Приведи получившийся код.

Автор: Redstuff 22.8.2007, 11:39
Idsa, содержание таблицы примерно такое (упрощенный пример):
 ID   |   Name   |  Photo  ....
 -----------------------------------
   1  | samsung |   pic1 .....
   2  | asus        |   null
   .........
Код

private void bMoveNext_Click(object sender, EventArgs e)
        {
            this.BindingContext[ds, "Hardware"].Position += 1;
            HardwareInfo();
            SqlCommand cmdSelect = new SqlCommand("select Photo from Hardware where ID=@ID", con);
            cmdSelect.Parameters.Add("@ID", SqlDbType.Int, 4);
            cmdSelect.Parameters["@ID"].Value = txtID.Text;
            con.Open();

            object barrImgObj = cmdSelect.ExecuteScalar(); //это до 8-й строчки
            if (barrImgObj != null)
            {
                byte[] barrImg = (byte[])barrImgObj; //это вместо строки 8
                string strfn = Convert.ToString(DateTime.Now.ToFileTime());
                FileStream fs = new FileStream(strfn, FileMode.CreateNew, FileAccess.Write);
                fs.Write(barrImg, 0, barrImg.Length);
                fs.Flush();
                fs.Close();

                Bitmap bmp = new Bitmap(strfn);
                pictureBox1.BackgroundImage = bmp;
                pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;

                ShowPosition();
            }
            con.Close();
        }

Автор: Idsa 22.8.2007, 11:57
Поставь breakpoint на строчку 11 и посмотри, чему равен barrImgObj для строки, в которой нет фотографии.

Автор: Redstuff 22.8.2007, 12:18
barrImgObj = {}
barrImg = null

Автор: Idsa 22.8.2007, 12:33
Действительно, значение не приводится к null...
Тогда предлагаю вот такой вариант через try-catch:
Код

 SqlCommand cmdSelect = new SqlCommand("select photo from testTable where ID=@ID", con);
      cmdSelect.Parameters.Add("@ID", SqlDbType.Int, 4);
      cmdSelect.Parameters["@ID"].Value = txtID.Text;
      try
      {
        con.Open();
        byte[] barrImg = (byte[])cmdSelect.ExecuteScalar();
        string strfn = Convert.ToString(DateTime.Now.ToFileTime());
        FileStream fs = new FileStream(strfn, FileMode.CreateNew, FileAccess.Write);
        fs.Write(barrImg, 0, barrImg.Length);
        fs.Flush();
        fs.Close();

        Bitmap bmp = new Bitmap(strfn);
        pictureBox1.BackgroundImage = bmp;
        pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;
        ShowPosition();
      }
      catch (InvalidCastException ex)
      {

      }
      finally 
      {
        con.Close();
      }

Автор: tol05 22.8.2007, 12:47
просто null и DBNull (который возвращается из базы при отсутсвии картинки) - это разные вещи... DBNull - это объект класса, а null - пустой указатель, указатель на ничто.
http://msdn2.microsoft.com/en-us/library/system.dbnull.aspx
Цитата

Do not confuse the notion of a null reference (Nothing in Visual Basic) in an object-oriented programming language with a DBNull object. In an object-oriented programming language, a null reference (Nothing in Visual Basic) means the absence of a reference to an object. DBNull represents an uninitialized variant or nonexistent database column.


Redstuff, ты не пробовал вместо if (barrImgObj != null) юзать  if (barrImgObj != DBNull.Value) ?


Автор: Idsa 22.8.2007, 13:04
Цитата(tol05 @  22.8.2007,  12:47 Найти цитируемый пост)
просто null и DBNull (который возвращается из базы при отсутсвии картинки) - это разные вещи

Действительно. Тогда получим два рабочих варианта:
Через if (с dbNll):
Код

private void bMoveNext_Click(object sender, EventArgs e)
        {
            this.BindingContext[ds, "Hardware"].Position += 1;
            HardwareInfo();
            SqlCommand cmdSelect = new SqlCommand("select Photo from Hardware where ID=@ID", con);
            cmdSelect.Parameters.Add("@ID", SqlDbType.Int, 4);
            cmdSelect.Parameters["@ID"].Value = txtID.Text;
            con.Open();
            object barrImgObj = cmdSelect.ExecuteScalar(); //это до 8-й строчки
            if (barrImgObj != DBNull.Value)
            {
                byte[] barrImg = (byte[])barrImgObj; //это вместо строки 8
                string strfn = Convert.ToString(DateTime.Now.ToFileTime());
                FileStream fs = new FileStream(strfn, FileMode.CreateNew, FileAccess.Write);
                fs.Write(barrImg, 0, barrImg.Length);
                fs.Flush();
                fs.Close();
                Bitmap bmp = new Bitmap(strfn);
                pictureBox1.BackgroundImage = bmp;
                pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;
                ShowPosition();
            }
            con.Close();
        }

и через try-catch:
Код

private void bMoveNext_Click(object sender, EventArgs e)
        {
            this.BindingContext[ds, "Hardware"].Position += 1;
            HardwareInfo();
          SqlCommand cmdSelect = new SqlCommand("select photo from testTable where ID=@ID", con);
      cmdSelect.Parameters.Add("@ID", SqlDbType.Int, 4);
      cmdSelect.Parameters["@ID"].Value = txtID.Text;
      try
      {
        con.Open();
        byte[] barrImg = (byte[])cmdSelect.ExecuteScalar();
        string strfn = Convert.ToString(DateTime.Now.ToFileTime());
        FileStream fs = new FileStream(strfn, FileMode.CreateNew, FileAccess.Write);
        fs.Write(barrImg, 0, barrImg.Length);
        fs.Flush();
        fs.Close();
        Bitmap bmp = new Bitmap(strfn);
        pictureBox1.BackgroundImage = bmp;
        pictureBox1.BackgroundImageLayout = ImageLayout.Stretch;
        ShowPosition();
      }
      catch (InvalidCastException ex)
      {
      }
      finally 
      {
        con.Close();
      }
        }

Если во второй вариант добавить catch'и для con.Open и fs.Write, то вообще красота получится smile

Автор: Redstuff 22.8.2007, 13:13
Спасибо все работает, но надо теперь чтобы было уведомление об отсутствии картинки или просто ее отсутствие в pictureBox.
Next
Код

catch (InvalidCastException ex)
            {
                pictureBox1.Image = Image.FromFile("C:\\notphoto.jpg");
            }

Когда попадаю на запись, которая не содержит картинки то вижу картинку notphoto.jpg
После двигаюсь дальше или в обратном направлении, она попрежнему висит
Пробовал так:
Код

pictureBox1.Image = Image.FromFile("C:\\notphoto.jpg");
pictureBox1.Image.Dispose();
pictureBox1.Image = null;

Но намного лучше не стало...

Пока писал уже 2 поста)

Автор: Idsa 22.8.2007, 13:33
Цитата(Redstuff @  22.8.2007,  13:13 Найти цитируемый пост)
Когда попадаю на запись, которая не содержит картинки то вижу картинку notphoto.jpg
После двигаюсь дальше или в обратном направлении, она попрежнему висит

Это потому что существующую картинку ты выводить через BackgroundImage, а "несуществующую" - через Image. Выбери один вариант и используй его для обоих случаев.

Автор: Redstuff 22.8.2007, 13:48
Idsa, спасибо!

Автор: Idsa 22.8.2007, 14:06
Цитата(Redstuff @  22.8.2007,  13:48 Найти цитируемый пост)
Idsa, спасибо! 

Рад помочь smile

Автор: tol05 22.8.2007, 16:05
OFFTOP...


Цитата(Idsa @  22.8.2007,  13:04 Найти цитируемый пост)
Действительно. Тогда получим два рабочих варианта:
 smile
не в обиду будь сказано, но...
обработку исключений обычно тогда, когда программист не может предусмотреть какая сложится run-time ситуация.
Здесь же налицо элементарная проверка типа возвращенного значения (малоизвестного, как оказалось, правда ... )

Не проще ли проверить тип полученного объекта (который явно может быть или DBNull или byte[]), и выйти из процедуры, чем ждать, пока CLR создат, инициализирует и выбросит объект исключения, а потом будет проверять по стеку наличие обработчика на перехват?..

есть еще третий рабочий вариант: в EntryPoint программы все загнать в AppDomain.UnhandledException и в обработчике написать что-то типа "Вах! Что-то прошло не так!" smile 

Автор: Idsa 22.8.2007, 16:22
tol05, вариант с try-catch предусматривал реализацию полноценной обработки исключений: InvalidCastException, SqlException... о чем я заявил выше:
Цитата(Idsa @  22.8.2007,  13:04 Найти цитируемый пост)
Если во второй вариант добавить catch'и для con.Open и fs.Write, то вообще красота получится smile 



Автор: Idsa 22.8.2007, 16:43
Кроме того, barrImgObj, помимо массива байт, может быть равен не только DbNull (в случае отсутствия картинки), но и null (если строка с заданным id отсуствует).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)