Как правильно хранить изображения в SQL и как правильно работать с ними в WPF проекте?

Ссылка скопирована
1 ответ

Я делаю программу, которая отдаленно напоминает Steam, только это для одной игры, т.е. это в приложении будет вся информация о определенной игре, моды различные и т.д. (забыл как подобные приложения называются).

Перейдем к сути. Вот как выглядит часть программы на данный момент:

Как правильно хранить изображения в SQL и как правильно работать с ними в WPF проекте?

Это список модов. У модов есть описание, тема, версии и т.д., но это не важно. Важно то, что у модов есть картинки. В правой формочке, где написано "Major Experimantals", очень много места и оно как раз таки под картинки. Вот как они хранятся в базе:

Как правильно хранить изображения в SQL и как правильно работать с ними в WPF проекте?

Есть колонка "MainImage", "FirstAdditionalImage", "SecondAdditionalImage" и тут хранятся картинки (тут не все заполнено). Я заполняю их путем прописывания пути, а в коде делаю так:

Как правильно хранить изображения в SQL и как правильно работать с ними в WPF проекте?

И вот я не совсем уверен, что это хороший способ хранить изображение в базе. В будущем я хотел бы попробовать сделать так, чтобы база была на каком-то сервере, чтобы многие могли пользоваться приложением, но не думаю, что это будет нормально работать, да и вообще не красиво( Заранее спасибо.

Дополнительно:

В правильную сторону думаете на счет сервера, только база не должна торчать наружу никак, обычно всё это делается через 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, да в общем-то много где картинки не являются чем-то очень защищённым. Те же соцсети тому пример
Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Андрей PHP Ответ

Для хранения изображений в SQL базе данных, можно использовать тип данных BLOB (Binary Large Object). Этот тип данных позволяет хранить большие объемы двоичных данных, таких как изображения.

Прежде всего, необходимо создать таблицу в базе данных, в которой будет храниться изображение. Пример SQL запроса для создания таблицы:

CREATE TABLE Images (
    Id INT PRIMARY KEY,
    ImageData BLOB
);

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();

$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;

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 проекте позволит эффективно управлять изображениями в приложении.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно