Как правильно хранить изображения в SQL и как правильно работать с ними в WPF проекте?
Я делаю программу, которая отдаленно напоминает Steam, только это для одной игры, т.е. это в приложении будет вся информация о определенной игре, моды различные и т.д. (забыл как подобные приложения называются).
Перейдем к сути. Вот как выглядит часть программы на данный момент:
Это список модов. У модов есть описание, тема, версии и т.д., но это не важно. Важно то, что у модов есть картинки. В правой формочке, где написано "Major Experimantals", очень много места и оно как раз таки под картинки. Вот как они хранятся в базе:
Есть колонка "MainImage", "FirstAdditionalImage", "SecondAdditionalImage" и тут хранятся картинки (тут не все заполнено). Я заполняю их путем прописывания пути, а в коде делаю так:
И вот я не совсем уверен, что это хороший способ хранить изображение в базе. В будущем я хотел бы попробовать сделать так, чтобы база была на каком-то сервере, чтобы многие могли пользоваться приложением, но не думаю, что это будет нормально работать, да и вообще не красиво( Заранее спасибо.
Дополнительно:
В правильную сторону думаете на счет сервера, только база не должна торчать наружу никак, обычно всё это делается через API, картинки так же.
Идеальное решение без лишних рассуждений
Картинки - в S3, а перед S3 поставить CDN, чтобы сильно S3 не нагружать.
В центральную базу данных на сервере - только идентификаторы картинок.
Клиент (на WPF) будет обращаться к какому-то приложению, которое написано на ASP NET Core, а оно, в свою очередь, будет идти в центральную БД за всякой инфой.
Опционально - клиент будет идти в CDN за картинками.
Сами картинки потом пусть кэшируются в ФС, чтобы не нужно было идти за ними повторно.
Данные о модах тоже можно кэшировать, но уже в sqlite - это полезно будет, пока нет интернета, или пока актуальный список модов загружается.
Да, единственный хороший вариант хранить картинки в базе - это не хранить картинки в базе, а хранить лишь пути или идентификаторы картинок.
Главный минус картинок в ФС - это то что они будут привязаны к одному серверу. Лучше хранить картинки в другой системе (S3 или CDN) и хранить в базе их идентификаторы, чтобы потом клиент мог сам их скачать, если это необходимо. Так раздача картинок не будет привязана к основному серверу.
А клиент пусть их кэширует также у себя на диске.
В будущем я хотел бы попробовать сделать так, чтобы база была на каком-то сервере, чтобы многие могли пользоваться приложением, но не думаю, что это будет нормально работать, да и вообще не красиво( Заранее спасибо.
Если ты хочешь, чтобы разные пользователи имели доступ к единой базе модов, то действительно надо сделать какой-то сервер.
Ну и клиент на WPF не должен напрямую подключаться к MS SQL.
MS SQL должен находится где-то на сервере и спрятан за каким-то другим web-сервером (который будет написан с использованием ASP NET Core например), который будет уже отвечать за всякую логику.
Если тебе нужна локальная база данных на клиенте (для кэша например), то лучше использовать sqlite.
- Честно признаться я мало что понял, ведь я не часто что-то делаю с MS SQL, только если лабы в колледже. Да и этот проект - первый опыт с mvvm (считаю, что сделал ошибку начав такой масштабный для меня проект используя этот паттерн, ибо я в будущем могу таких костылей наделать, что трудно себе представить).
По поводу хранения изображения и, я так понимаю, прослойки в виде web-сервера. Я в голове у себя что-то дернул и что-то даже понял, но все-таки, есть какие-то гайды на все вот это вот?
- EboLiK, Василий Банников уже ответил на этот вопрос, но есть подробное руководство по веб API.Net и клиенте на ASP.NET MVC, где в том числе, рассматривается вопрос автоматизации загрузки и хранения файлов изображений на локальном сервере с передачей в базу данных ссылок на такие файлы, вот вводное видео. И эта схема не совсем то что нужно для проекта на WPF, однако эти же подходы к решению проблемы, можно использовать и для монолитного приложения на WPF.
Ответы:
Ну вообще-то хранение изображений в полях базы данных считается антипаттерном... а по сути - это вообще худшее из возможных решений.
Наилучшее решение - файлы хранятся в FileTables либо FILESTREAM, а в таблице лежат ссылки на них. Что приятно - при этом не надо распыляться с безопасностью, за ней следит SQL Server.
Сравнение параметров для хранения больших двоичных...
Можно, конечно, хранить файлы и в файловой системе. Но тогда вышеупомянутая безопасность разваливается на две независимые и несвязанные части... и обе требуют внимания и поддержки.
PS. Пройдя по ссылке - обязательно прочитать и оригинальный ихнеязычный текст. Как, впрочем, и для любого другого машиннопереведённого текста.
-
Ну вообще-то хранение изображений в полях базы данных считается антипаттерном... а по сути - это вообще худшее из возможных решений.
Наилучшее решение - файлы хранятся в FileTables либо FILESTREAM, а в таблице лежат ссылки на них. Что приятно - при этом не надо распыляться с безопасностью, за ней следит SQL Server.
Нет, это не наилучшее, так как оно лишний раз нагружает СУБД и не очень cdn-friendly.
Те картинки, которые можно - лучше выдавать без авторизации.
Случай автора как раз такой - Василий Банников, вероятно, это особенность предметной области? в веб-интерфейсах и играх не силён.
- Akina, да в общем-то много где картинки не являются чем-то очень защищённым. Те же соцсети тому пример
Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.
Пока нет других ответов. Будьте первым, кто поможет автору.
Ответить на вопрос



Для хранения изображений в SQL базе данных, можно использовать тип данных BLOB (Binary Large Object). Этот тип данных позволяет хранить большие объемы двоичных данных, таких как изображения.
Прежде всего, необходимо создать таблицу в базе данных, в которой будет храниться изображение. Пример SQL запроса для создания таблицы:
CREATE TABLE Images ( Id INT PRIMARY KEY, ImageData BLOB );
После создания таблицы, можно добавить изображение в базу данных. Для этого необходимо прочитать содержимое изображения в бинарном формате и выполнить SQL запрос для добавления данных в таблицу. Пример кода на языке PHP для добавления изображения:
$imageData = file_get_contents('path/to/image.jpg'); $query = "INSERT INTO Images (Id, ImageData) VALUES (1, :imageData)"; $stmt = $pdo->prepare($query); $stmt->bindParam(':imageData', $imageData, PDO::PARAM_LOB); $stmt->execute();
После того как изображение сохранено в базе данных, можно его извлечь и отобразить в WPF проекте. Для этого необходимо выполнить SQL запрос для извлечения данных из таблицы и преобразовать бинарные данные в изображение. Пример кода на языке C# для работы с изображением в WPF проекте:
using System; using System.Data; using System.Data.SqlClient; using System.IO; using System.Windows.Media.Imaging; string connectionString = "Data Source=your_server;Initial Catalog=your_database;Integrated Security=True"; string query = "SELECT ImageData FROM Images WHERE Id = 1"; byte[] imageData; using (SqlConnection connection = new SqlConnection(connectionString)) { connection.Open(); SqlCommand command = new SqlCommand(query, connection); using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess)) { if (reader.Read()) { imageData = (byte[])reader["ImageData"]; } } } BitmapImage image = new BitmapImage(); using (MemoryStream stream = new MemoryStream(imageData)) { image.BeginInit(); image.StreamSource = stream; image.CacheOption = BitmapCacheOption.OnLoad; image.EndInit(); } // Отобразить изображение в WPF элементе Image yourImageElement.Source = image;
Таким образом, правильное хранение изображений в SQL и работа с ними в WPF проекте позволит эффективно управлять изображениями в приложении.