Tag Archives: categories

Как да извлечем картинките от базата данни Northwind с помощта на C#, ADO.NET и SQL Server 2008 R2?

Какво представлява Northwind?

nortwind traders database logoБазата данни Northwind съдържа данните за продажбите на имагинерна фирма, която внася и изнася храни по целия свят. Тя е била създадена от Microsoft като проста база, която да се използва с техните продукти – Access и SQL Server. Известна е с това, че е построена много добре и е перфектна за учебни цели. Във w3schools например, сайт с онлайн туториали, базата на Northwind Traders се използва в SQL примерите. Можете да изтеглите скрипта на Northwind за SQL Server 2008 R2 от тук.

Какво е OLE?

През 1990 екипът в Microsoft, който разработва Access се нуждаел от начин не само да съхранява данни, но и да я предоставя на потребител, който е качил и друг софтуер на компютъра си. Тогава е нямало надежден начин да откриеш чрез операционната система кой софтуер с какви типове файлове работи. На тях им дошла идея, която била наречена Object Linking and Embedding(OLE).

Как се съхраняват файлове с OLE структура?

OLE структурата представлява следното:

  1. Пакетен header
  2. Ole header
  3. Datablock header
  4. Данни
  5. Metafilepict блок
  6. Ole footer

Когато се работи с картинки, има блок, който се нарича metafilepict. Едва ли ще откриете картинка, ако го прочетете. Стартовата позиция на картинката се изчислява след като се изпусне този блок.
Metafilepict стартова позиция = дължината на package header-а + дължината на ole header-а + 8 празни байта + 4 байта, указващи дължината на данните + дължината на байтовете + 45 (дължината на metafilepict header-а). При картинките в Northwind това число е точно 78.

Четене на images от таблица Categories в Northwind

След като вече знаем, че трябва да прескочим 78 байта, за да прочетем картинката, просто трябва да го напишем. Използвам код на C# и доста остарялата технология ADO.NET, но тя ще свърши перфектна работа за простия пример.
Кодът на C#:

int OLE_METAFILEPICT_START_POSITION = 78;

SqlConnection con = new SqlConnection(
    "Server=.\\SQLEXPRESS; " +
    "Database=Northwind; " +
    "Integrated Security=true");
con.Open();
using (con)
{
    SqlCommand command = new SqlCommand(
        "SELECT CategoryName, Picture " +
        "FROM Categories", con);
    SqlDataReader reader = command.ExecuteReader();
                
    using (reader)
    {
        while (reader.Read())
        {
            string categoryName = ((string)reader["CategoryName"]);
            if (categoryName.Contains('/') == true)
            {
                categoryName = categoryName.Replace('/', ' ');
            }
            byte[] pictureBytes = reader["Picture"] as byte[];
                        
            MemoryStream stream = new MemoryStream(
                pictureBytes, OLE_METAFILEPICT_START_POSITION,
                pictureBytes.Length - OLE_METAFILEPICT_START_POSITION);	
						
            Image image = Image.FromStream(stream);
            using (image)
            {
                image.Save(categoryName + ".jpg", ImageFormat.Jpeg);
            }
        }                    
    }                
}

Картинките:
northwind images from categories table