Лучший способ ссылаться на статические данные базы данных в коде?

24

Многие приложения включают в себя «статические данные»: данные, которые на самом деле не меняются в течение всего срока службы приложения. Например, у вас может быть список торговых площадок, которые, вероятно, будут фиксированным списком в обозримом будущем.

Нередко эти статические данные можно найти в таблице базы данных (часто потому, что вы хотите ссылаться на них во внешних ключах других таблиц). Простой пример таблицы будет иметь идентификатор для использования в качестве первичного ключа и описание. Например, ваша таблица SalesArea будет иметь (как минимум) столбец SalesAreaId и столбец SalesAreaDescription.

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

Каков наилучший способ ссылаться на эти статические данные в коде? Зачем?

  1. Жесткий код описания в вашем коде. Используйте это для поиска SalesAreaId из базы данных, когда вам это нужно.
  2. Жесткий код идентификаторов в вашем коде. Используйте это, чтобы найти SalesAreaDescription, когда вам это нужно.
  3. Добавьте столбец в таблицу для каждой цели, например, столбец «IsDefaultOnProductLaunchScreen» и т. Д. (Их может быть много).
  4. Что-то другое.

Есть ли какие-то особые соображения, которые я должен учитывать при работе со статическими данными базы данных? Например, дать этим таблицам специальное имя?

Kramii Восстановить Монику
источник
1
Возможный дубликат: programmers.stackexchange.com/questions/304169/… Я считаю, что ответы на этот вопрос (связанный) немного лучше
раскрывают

Ответы:

14

Как насчет загрузки их в кеш (обычно реализуемый в виде хеш-таблицы) при запуске приложения? Если вы сделаете это, вам даже не придется запрашивать базу данных (ну, не более одного раза).

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

FrustratedWithFormsDesigner
источник
Кэширование, конечно, хорошо, но как вы обновите эти значения? Предположительно, перезапуск приложения или какая-то стратегия аннулирования кэша?
Стив
1
@ Стив Да, точно. Зависит от приложения. Перезапуск хорош для чего-то, что часто начинается. Для долго работающего приложения, возможно, перезагрузка кеша один раз в день в медленное время. Мой вопрос был бы, как насчет сценария, в котором приложение работает очень короткое время. Например, сценарий PHP или что-то похожее.
Tylermac
База данных будет запускать свой собственный кеш для часто используемых данных, поэтому вы будете повторно реализовывать то, что уже реализовано (и, вероятно, не так хорошо!)
Джеймс Андерсон
@JamesAnderson: Кэширование в средство приложения будет только когда - либо будет один вызов к базе данных. Да, базы данных будут иметь свои собственные кэши, но они могут быть аннулированы / обновлены событиями, находящимися вне контроля вашего приложения, и вам все равно нужно подключиться к базе данных и сделать запрос для получения этих данных (и надеяться, что он находится в кэш БД). Это действительно не так сложно реализовать простой кэш в приложении.
FrustratedWithFormsDesigner
7

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

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

Стив
источник
1
Хорошая идея для некоторых типов статических данных, но не очень хорошая, если вы хотите применить отношения FK, как описано в вопросе.
Kramii восстановит Монику
Вопрос не говорил, что это требование, только сценарий. Если это не нужно, тогда подход с использованием файла конфигурации работает хорошо.
Стив
Вы правы, я не был достаточно ясен. Но мне приятно ... потому что я узнал кое-что из твоего ответа. Я никогда не сталкивался с таким подходом раньше.
Крами восстановит Монику
3

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

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

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

прецизионный самописец
источник
«Часто то, что мы считаем статичным, оказывается не таким», - так верно.
Kramii восстановит Монику
3

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

В простом приложении у меня в настоящее время есть список состояний редактирования для частей контента: Черновик, Опубликованный, Архивированный.

Элементы содержимого должны обрабатываться по-разному, в зависимости от того, в каком состоянии они находятся. Если бы я сохранял эти данные состояния в БД со значениями 1, 2, 3 соответственно, как бы я проверил, находится ли что-то в черновике? штат?

if (content.State == 1)
или
if (content.State == "Draft")?

Я просто жестко закодировал значения!
То же самое, если вы используете кеш / хэш-таблицу: вам все равно нужно использовать какое-то значение, записанное в вашем коде, в качестве ключа для поиска ваших данных.

Каковы недостатки жесткого подхода?

Дейв
источник
Недостаток, как сказал pdr: «Часто то, что мы считаем статичным, оказывается не таким».
Tylermac
2
Но если вы на самом деле ссылаетесь на значения статических данных в коде, вы не можете изменить их в базе данных, не сломав приложение. Конечно, это зависит от того, для чего используются данные: как я уже говорил выше, если он просто заполняет элемент пользовательского интерфейса, чтобы пользователь мог выбрать значение и передать его обратно в БД как часть записи в другой таблице. то статические данные в БД могут меняться независимо от кода приложения. Я уверен, что именно об этом говорит @pdr: приложение обрабатывает набор статических данных как один элемент.
Дейв
2

Подобно тому, что сказал FrustratedWithFormsDesigner, это обычно делается с кешем, поскольку это означает, что вам когда-либо нужно загружать статические данные только один раз, но это следует шаблону OAOO, то есть мы не определяем данные в двух местах (база данных и ваш код).

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

Скотт Уитлок
источник
+1 за один раз и только один раз. Но как по-разному относиться к разным рядам?
Kramii восстановит Монику
1
@Kramii - Вы можете использовать что-то вроде перечисления классов . Если метаданные относятся только к вашей программе, то я бы поместил бизнес-логику ( IsDefaultOn...) в свойство объекта. Пусть это вернет истину для одной сущности. Это позволило бы вам найти эту сущность, учитывая всю коллекцию. Или вы можете использовать класс контроллера, который предоставит вам соответствующий объект с вызовом метода.
Скотт Уитлок
2

Это преждевременная оптимизация в худшем случае.

Во-первых, любая современная СУБД будет извлекать данные из небольших таблиц с молниеносной скоростью, и все они имеют алгоритмы кэширования от хорошего до превосходного (чем больше вы заплатите за СУБД, тем лучше кэширование!). Таким образом, вы оптимизируете то, что потребляет минимальные ресурсы.

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

Здесь есть только два пути:

Сохраните его в базе данных и получите доступ к данным с помощью «обычного» sql.

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

Джеймс Андерсон
источник
1

Это зависит от того, что вы делаете с данными. Если это список чего-то, я обычно вытаскиваю его в массив. Если список необходимо увеличить в другой версии, легко добавить в базу данных и изменить код для обработки дополнительных данных в массиве (что может даже не потребоваться в зависимости от кода, например, перечисление данных с цикл for с использованием верхней границы массива). Если это список настроек, я обычно буду жестко их кодировать, поскольку их обычно не так много, и это проще и быстрее, чем с помощью оператора SQL. Если это параметр, который пользователь может изменить, и я хочу сохранить выбор для последующих запусков, я создам таблицу для использования в качестве реестра и просто извлекаю отдельные записи в переменные по мере необходимости.

MaQleod
источник
1

Я знаю, что этот ответ был принят, но я хотел поделиться тем, как мы это делали, в моем последнем магазине веб-разработки, где мы старались максимально сократить количество операций ввода-вывода в базе данных.

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

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

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

Майкл Райли - AKA Gunny
источник
0

Мое решение, которое может работать не во всех ситуациях, - это привязать статические данные базы данных к жестко закодированным enum. Поскольку проблема возникает из-за привязки динамических данных (базы данных) к статической логике (коду), сделайте эту привязку явной (и свободной), имея таблицу базы данных, которая связана с enum. Пример:

LooseDBCodeBinding (database table)
   ID : Int32 (key)
   Name : String
   HardCodedTypeID : Int32

// in code:
public enum LooseDBCodeBinding
{
   TYPE_1 = 1,
   TYPE_2 = 2,
   TYPE_3 = 3 // etc...
}

Затем напишите пользовательский интерфейс, который позволяет легко просматривать список LooseDBCodeBindingзаписей и сопоставлять их со LooseDBCodeBinding enumзначениями (включая поддержку «сломанных» привязок). Затем вы можете программировать enumи проектировать базу данных по ключу таблицы, и только эта таблица знает оба контекста.

Дейв Кузино
источник