Хорошая ли идея создавать БД на стороне клиентской части (фронтенда)?

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

Насколько хорошая идея создавать таблицу, колонки БД на стороне клиентской части (фронтенда)? Какие проблемы могут возникнуть в будущем, и стоит ли это делать в целом?

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

Если говорить о web, то на клиентской стороне для хранения данных доступны только LocalStorage(SessionStorage) и IndexedDB. Таблиц и колонок в них как таковых нет, поэтому, полагаю, речь идет не об этом.
Уточните, пожалуйста, свой вопрос.

  • А какие вы видите у этой идеи плюсы, зачем это делать?
  • Зависит от многих факторов:
    1. Если это полноценное офлайн приложение:
    - Если необходима полноценная СУБД (SQL Server, Postgres, MySql) - то нет. Мало кто захочет дополнительно себе устанавливать такие тяжелые зависимости, они всегда могут ее удалить и тогда уже не восстановить, обновления ПО либо не будут возможны, либо трудны
    - Если это встраиваемая СУБД (SQLite) - то вполне да, так многие приложения делают (на андроиде слышал SQLite часто используют)
    2. Если это онлайн приложение в браузере:
    - localStorage - это key/value хранилище
    - web sql - устаревшая технология
    - куки - могут пропасть в любое время
    3. Если это корпоративные клиенты, то можно навязать им свои требования по необходимости запуска СУБД на каждой машине

    Тут все зависит от того, что под БД подразумевается и для каких целей это нужно

    UPD: SQL запросы из клиента напрямую в БД - очень плохая идея, не надо так (обновления, безопасность, гибкость и т.д. - все постарадает)

    • Суть в том, что имеющие SQL запросы (INSERT, JOINT LEFT - RIGT) делать на стороне клиента, и я задался вопросом себе, насколько это нужная задача, и какие аргументы мог бы противопоставить, что это нужно - не нужно?
    • laravel_creative_3103, ни в коем случае:
      - сложность обновления приложения
      - высокая нагрузка на БД (т.к. в обход кэша это будет происходить)
      - (самое главное) безопасность - по факту каждый желающий будет иметь доступ к продовой базе
    • Сергей Соловьев, Здесь такой момент, что на стороне клиента будут отправляться определенные поля, с помощью которого будет создаваться таблица и колонки для таблиц. На стороне сервера не будет происходить миграции, а именно пример кода будет таков на стороне сервера:
      public IActionResult CreateForm([FromBody] CreateForm model)         {             try             {                 using IDbConnection db = new NpgsqlConnection("postgres");                  var createFormsTable = @$"create table if not exists ""forms"" (                     form_name text,                     table_name text,                     columns text[]                 );".Replace("n", " ").Replace("t", " ").Replace("r", " ").TrimEnd(',');                 db.Execute(createFormsTable);                  foreach (var form in model.Forms)                 {                     var columnsBuilder = new StringBuilder();                     foreach (var item in form.Columns)                     {                         columnsBuilder.Append(@$"'{item}',");                     }                     var columns = columnsBuilder.ToString().TrimEnd(',');                     var insertForm = @$"insert into ""forms"" values ('{model.FormName}','{form.TableName}', array [{columns}]);";                     db.Execute(insertForm);                 }                                  return Ok();             }

      public IActionResult CreateForm([FromBody] CreateForm model) { try { using IDbConnection db = new NpgsqlConnection("postgres"); var createFormsTable = @$"create table if not exists ""forms"" ( form_name text, table_name text, columns text[] );".Replace("n", " ").Replace("t", " ").Replace("r", " ").TrimEnd(','); db.Execute(createFormsTable); foreach (var form in model.Forms) { var columnsBuilder = new StringBuilder(); foreach (var item in form.Columns) { columnsBuilder.Append(@$"'{item}',"); } var columns = columnsBuilder.ToString().TrimEnd(','); var insertForm = @$"insert into ""forms"" values ('{model.FormName}','{form.TableName}', array [{columns}]);"; db.Execute(insertForm); } return Ok(); }

    • laravel_creative_3103, ты только что показал прямую SQL инъекцию

    СУБД на стороне клиента разработчику нужно воспринимать только в качестве разновидности кеша данных, для которого по счастливому случаю предусмотрен API в виде SQL.
    Какие проблемы?
    - Все те, что есть у любой подсистемы, что обеспечивает кеширование. То есть, нужно следить, чтобы в ней находились только актуальные данные. Обеспечивать своевременную синхронизацию данных с сервером, решать конфликты кеша и данных сервера. Если у вас для пользователя предусмотрено ведение учетной записи, то в локальную базу данных не должно загружаться никаких данных, не предусмотренные правами доступа пользователя.

    В любом случае, у вас эксклюзивная часть приложения, в которой, например, ведутся сведения об учетных записях пользователей, хранится состояние лицензий, должна находится на сервере. И там будет нормальная, взрослая СУБД.

    Суть в том, что имеющие SQL запросы (INSERT, JOINT LEFT - RIGT) делать на стороне клиента, и я задался вопросом себе, насколько это нужная задача, и какие аргументы мог бы противопоставить, что это нужно - не нужно?

    Если вы хотите собирать текст запросов на клиенте, передавать на сервер, и там исполнять.
    Не самый хороший вариант, но терпимо только в одном случае, если учетная запись пользователя в точности соответствует учетной записи в СУБД, и доступ к данным в СУБД четко ограничен правами доступа - из учетной записи в СУБД нельзя дотянуться ни до каких данных, не принадлежащих только этому пользователю.
    Но такое редко бывает, так что воздержитесь от этой практики, воспользуйтесь лучше GraphQL/TreeQL, чтобы ограничить API только тем функционалом и теми данными, которые необходимы для конкретного пользователя.

    • Здесь такой момент, что на стороне клиента будут отправляться определенные поля, с помощью которого будет создаваться таблица и колонки для таблиц. На стороне сервера не будет происходить миграции, а именно пример кода будет таков на стороне сервера:
      public IActionResult CreateForm([FromBody] CreateForm model)         {             try             {                 using IDbConnection db = new NpgsqlConnection("postgres");                  var createFormsTable = @$"create table if not exists ""forms"" (                     form_name text,                     table_name text,                     columns text[]                 );".Replace("n", " ").Replace("t", " ").Replace("r", " ").TrimEnd(',');                 db.Execute(createFormsTable);                  foreach (var form in model.Forms)                 {                     var columnsBuilder = new StringBuilder();                     foreach (var item in form.Columns)                     {                         columnsBuilder.Append(@$"'{item}',");                     }                     var columns = columnsBuilder.ToString().TrimEnd(',');                     var insertForm = @$"insert into ""forms"" values ('{model.FormName}','{form.TableName}', array [{columns}]);";                     db.Execute(insertForm);                 }                                  return Ok();             }

      public IActionResult CreateForm([FromBody] CreateForm model) { try { using IDbConnection db = new NpgsqlConnection("postgres"); var createFormsTable = @$"create table if not exists ""forms"" ( form_name text, table_name text, columns text[] );".Replace("n", " ").Replace("t", " ").Replace("r", " ").TrimEnd(','); db.Execute(createFormsTable); foreach (var form in model.Forms) { var columnsBuilder = new StringBuilder(); foreach (var item in form.Columns) { columnsBuilder.Append(@$"'{item}',"); } var columns = columnsBuilder.ToString().TrimEnd(','); var insertForm = @$"insert into ""forms"" values ('{model.FormName}','{form.TableName}', array [{columns}]);"; db.Execute(insertForm); } return Ok(); }

    • Спроектируйте структуру базы данных так, чтобы приложение использовало только DML SQL - работать только с данными. Только разработчик должен пользоваться DDL SQL - создавать и изменять структуру базы.

    Я это ранее хорошо описал в ответе на этот вопрос. Вкратце, всё что находится на стороне клиента доступно пользователю. Соответственно, пользователь сможет напрямую вмешиваться в работу этой части веб-приложения. А это значит, что недобросовестный пользователь может поломать валидацию, запросы и другие вещи. По этому, это нужно размещать на сервере, к которому пользователь не имеет прямого доступа. Соответственно именно сервер занимается обработкой запроса, валидациями и запросами в БД

    • Здесь такой момент, что на стороне клиента будут отправляться определенные поля, с помощью которого будет создаваться таблица и колонки для таблиц. На стороне сервера не будет происходить миграции, а именно пример кода будет таков на стороне сервера:
      public IActionResult CreateForm([FromBody] CreateForm model)         {             try             {                 using IDbConnection db = new NpgsqlConnection("postgres");                  var createFormsTable = @$"create table if not exists ""forms"" (                     form_name text,                     table_name text,                     columns text[]                 );".Replace("n", " ").Replace("t", " ").Replace("r", " ").TrimEnd(',');                 db.Execute(createFormsTable);                  foreach (var form in model.Forms)                 {                     var columnsBuilder = new StringBuilder();                     foreach (var item in form.Columns)                     {                         columnsBuilder.Append(@$"'{item}',");                     }                     var columns = columnsBuilder.ToString().TrimEnd(',');                     var insertForm = @$"insert into ""forms"" values ('{model.FormName}','{form.TableName}', array [{columns}]);";                     db.Execute(insertForm);                 }                                  return Ok();             }

      public IActionResult CreateForm([FromBody] CreateForm model) { try { using IDbConnection db = new NpgsqlConnection("postgres"); var createFormsTable = @$"create table if not exists ""forms"" ( form_name text, table_name text, columns text[] );".Replace("n", " ").Replace("t", " ").Replace("r", " ").TrimEnd(','); db.Execute(createFormsTable); foreach (var form in model.Forms) { var columnsBuilder = new StringBuilder(); foreach (var item in form.Columns) { columnsBuilder.Append(@$"'{item}',"); } var columns = columnsBuilder.ToString().TrimEnd(','); var insertForm = @$"insert into ""forms"" values ('{model.FormName}','{form.TableName}', array [{columns}]);"; db.Execute(insertForm); } return Ok(); }

    • laravel_creative_3103, в таком случае это допустимо, т.к. у вас отправка в БД стоит на сервере, на у вас до сих пор нет валидаций. Если это учебный/тестовый проект, тогда вполне сойдёт.
    • Nik Faraday, но вполне возможно, что это перерастет в большой продовой проект, с помощью чего SQL запросы будут формироваться через интерфейс клиентской части. На сервере будет примерно такой код, который я скидывал раннее. Суть задачи в том, что условно у вас есть 5 инпутов в html, и 5 колонок в таблице. Для того, чтобы добавить шестой(6) инпут, нужно будет где-то в настройках добавить шестой инпут, и без миграции добавиться шестая колонка, и шестой инпут.
    • laravel_creative_3103, миграцию нужно делать когда вы изменяете саму модель данных. В вашем случае, там будет отношение один ко многим, и при добавлении инпута будет делаться новая запись в БД. Тут и так, и так миграции не нужны.

      А вообще, если хотите использовать БД без нужды в миграциях, используйте NoSql облачные БД, тот же MongoDb, там есть именно тот функционал, что вам нужен. Отправку туда можете сделать хоть с чистого JS, но лучше всё же такие вещи делать на сервере

    • Nik Faraday,
      В таком случае такой пример:
      [HttpPost("column")]         public IActionResult AddColumn(AddColumn model)         {             try             {                 using IDbConnection db = new NpgsqlConnection("postgres");                  var addColumn = @$"alter table ""{model.TableName}"" add column ""{model.ColumnName}"" text;"                                     .Replace("n", " ").Replace("t", " ").Replace("r", " ").TrimEnd(',');                 db.Execute(addColumn);                 return Ok();             }             catch (Exception e)             {                 return BadRequest(e.Message);             }         }

      [HttpPost("column")] public IActionResult AddColumn(AddColumn model) { try { using IDbConnection db = new NpgsqlConnection("postgres"); var addColumn = @$"alter table ""{model.TableName}"" add column ""{model.ColumnName}"" text;" .Replace("n", " ").Replace("t", " ").Replace("r", " ").TrimEnd(','); db.Execute(addColumn); return Ok(); } catch (Exception e) { return BadRequest(e.Message); } }

    • laravel_creative_3103, та не колонку)

      Вы две таблицы сделайте с готовыми колонками и просто свяжите их связью один ко многим

    Нужно решить такую задачу?

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

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

    Создание базы данных на стороне клиентской части (фронтенде) может быть привлекательной идеей в определенных случаях, но обычно не рекомендуется из-за ряда проблем и ограничений.

    Во-первых, безопасность данных является основной проблемой при создании БД на стороне клиента. Поскольку весь код и данные хранятся на клиентской стороне, это делает информацию более уязвимой для атак. К тому же, пользователи могут легко получить доступ к данным и изменять их, что может привести к различным проблемам с целостностью информации.

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

    Кроме того, создание БД на стороне клиента не позволяет легко масштабировать систему и управлять данными. Например, сложно обеспечить согласованность данных и их резервное копирование.

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

    Если вам необходимо хранить небольшие объемы данных на клиентской стороне для повышения производительности или улучшения пользовательского опыта, можно использовать локальное хранилище браузера или кэширование данных. Однако для хранения больших объемов информации рекомендуется использовать серверную базу данных.

    Пример использования локального хранилища браузера в JavaScript:

    // Сохранение данных в локальное хранилище
    localStorage.setItem('key', 'value');
     
    // Получение данных из локального хранилища
    var value = localStorage.getItem('key');

    // Сохранение данных в локальное хранилище localStorage.setItem('key', 'value'); // Получение данных из локального хранилища var value = localStorage.getItem('key');

    В общем, хотя создание БД на стороне клиента может быть возможным в некоторых случаях, обычно рекомендуется использовать серверную базу данных для обеспечения безопасности, производительности и управляемости данных.

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

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

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

    комментарий

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

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