Рассмотрим, как мы можем сохранять файлы, в частности, файлы изображений в базу данных. Для этого создадим новую базу данных и в ней новую таблицу Files с четырьмя столбцами:
Id - первичный ключ и идентификатор, имеет тип int)
FileName будет хранить имя файла и имеет тип nvarchar
Title будет хранить заголовок файла и также имеет тип nvarchar
ImageData будет содержать бинарные данные файла и имеет тип varbinary(MAX)
Для создания базы данных и таблицы для хранения файлов определим следующую программу:
using System; using System.Threading.Tasks; using Microsoft.Data.SqlClient; namespace HelloApp { class Program { static async Task Main(string[] args) { string connectionString = "Server=(localdb)\\mssqllocaldb;Database=master;Trusted_Connection=True;"; string sqlExpression = "CREATE DATABASE filesdb"; // создаем базу данных using (SqlConnection connection = new SqlConnection(connectionString)) { await connection.OpenAsync(); SqlCommand command = new SqlCommand(sqlExpression, connection); await command.ExecuteNonQueryAsync(); Console.WriteLine("База данных создана"); } connectionString = "Server=(localdb)\\mssqllocaldb;Database=filesdb;Trusted_Connection=True;"; sqlExpression = @"CREATE TABLE Files (Id INT PRIMARY KEY IDENTITY, Title NVARCHAR(50) NOT NULL, FileName NVARCHAR(50) NOT NULL, ImageData varbinary(MAX))"; // создаем таблицу using (SqlConnection connection = new SqlConnection(connectionString)) { await connection.OpenAsync(); SqlCommand command = new SqlCommand(sqlExpression, connection); await command.ExecuteNonQueryAsync(); Console.WriteLine("Таблица Files создана"); } Console.Read(); } } }
Определим код, в котором будут загружаться данные в таблицу:
using System; using System.Data; using System.IO; using System.Threading.Tasks; using Microsoft.Data.SqlClient; namespace HelloApp { class Program { static async Task Main(string[] args) { await SaveFileToDatabaseAsync(); Console.Read(); } private static async Task SaveFileToDatabaseAsync() { string connectionString = "Server=(localdb)\\mssqllocaldb;Database=filesdb;Trusted_Connection=True;"; using (SqlConnection connection = new SqlConnection(connectionString)) { await connection.OpenAsync(); SqlCommand command = new SqlCommand(); command.Connection = connection; command.CommandText = @"INSERT INTO Files VALUES (@FileName, @Title, @ImageData)"; command.Parameters.Add("@FileName", SqlDbType.NVarChar, 50); command.Parameters.Add("@Title", SqlDbType.NVarChar, 50); // путь к файлу для загрузки string filename = @"D:\forest.jpg"; // заголовок файла string title = "Лес"; // получаем короткое имя файла для сохранения в бд string shortFileName = filename.Substring(filename.LastIndexOf('\\') + 1); // forest.jpg // массив для хранения бинарных данных файла byte[] imageData; using (FileStream fs = new FileStream(filename, FileMode.Open)) { imageData = new byte[fs.Length]; fs.Read(imageData, 0, imageData.Length); command.Parameters.Add("@ImageData", SqlDbType.Image, Convert.ToInt32(fs.Length)); } // передаем данные в команду через параметры command.Parameters["@FileName"].Value = shortFileName; command.Parameters["@Title"].Value = title; command.Parameters["@ImageData"].Value = imageData; await command.ExecuteNonQueryAsync(); Console.WriteLine("Файл сохранен"); } } } }
После выполнения этой программы в базе данных появится соответствующая запись:
Хотя в данном случае загружается изображение, но это частный случай, в принципе можно использовать и другие типы файлов.
Теперь произведем обратную операцию - получим файл из БД. Вначале определим класс файла, который упростит работу с данными:
public class Image { public Image(int id, string filename, string title, byte[] data) { Id = id; FileName = filename; Title = title; Data = data; } public int Id { get; private set; } public string FileName { get; private set; } public string Title { get; private set; } public byte[] Data { get; private set; } }
Затем в коде программы определим следующий метод:
using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Threading.Tasks; using Microsoft.Data.SqlClient; namespace HelloApp { class Program { static async Task Main(string[] args) { await ReadFileFromDatabaseAsync(); Console.Read(); } private static async Task ReadFileFromDatabaseAsync() { string connectionString = "Server=(localdb)\\mssqllocaldb;Database=filesdb;Trusted_Connection=True;"; List<Image> images = new List<Image>(); using (SqlConnection connection = new SqlConnection(connectionString)) { await connection.OpenAsync(); string sql = "SELECT * FROM Files"; SqlCommand command = new SqlCommand(sql, connection); using (SqlDataReader reader = await command.ExecuteReaderAsync()) { while (await reader.ReadAsync()) { int id = reader.GetInt32(0); string filename = reader.GetString(1); string title = reader.GetString(2); byte[] data = (byte[])reader.GetValue(3); Image image = new Image(id, filename, title, data); images.Add(image); } } } // сохраним первый файл из списка if (images.Count > 0) { using (FileStream fs = new FileStream(images[0].FileName, FileMode.OpenOrCreate)) { fs.Write(images[0].Data, 0, images[0].Data.Length); Console.WriteLine($"Файл {images[0].Title} сохранен"); } } } public class Image { public Image(int id, string filename, string title, byte[] data) { Id = id; FileName = filename; Title = title; Data = data; } public int Id { get; private set; } public string FileName { get; private set; } public string Title { get; private set; } public byte[] Data { get; private set; } } }
В этом методе с помощью SqlDataReader мы получаем значения из БД и по ним создаем объект Image, который потом добавляется в список. И в конце смотрим, если в списке есть элементы, то берем первый элемент и сохраняем его на локальный компьютер. И после сохранения в папке нашей программы появится загруженный из базы данных файл.