Подтвердить что ты не робот

Каковы шаблоны проектирования для поддержки настраиваемых полей в приложении?

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

Каковы известные шаблоны проектирования для хранения значений полей и метаданных о полях?

Я вижу следующие параметры:

Вариант 1: добавьте поля Field1, Field2, Field3, Field4 типа varchar в таблицу Customer.

Вариант 2. Добавьте один столбец типа XML в таблицу клиентов и сохраните значения настраиваемых полей в xml.

Вариант 3: добавьте таблицу CustomerCustomFieldValue со столбцом типа varchar и сохраните значения в этом столбце. Эта таблица также будет иметь идентификатор CustomerID, CustomFieldID.

CustomerID,  CustomFieldID, Value
10001,       1001,          '02/12/2009 8:00 AM'
10001,       1002,          '18.26'
10002,       1001,          '01/12/2009 8:00 AM'
10002,       1002,          '50.26'

CustomFieldID будет идентификатором из другой таблицы под названием CustomField с этими столбцами: CustomFieldID, FieldName, FieldValueTypeID.

Вариант 4: добавьте таблицу CustomerCustomFieldValue со столбцом каждого возможного типа значений и сохраните значения в правом столбце. Аналогично # 3, но значения полей хранятся с использованием столбца строгого типа.

CustomerID,  CustomFieldID, DateValue,           StringValue,       NumericValue                 
10001,       1001,          02/12/2009 8:00 AM,  null,              null
10001,       1002,          null,                null,              18.26
10002,       1001,          01/12/2009 8:00 AM,  null,              null
10002,       1002,          null,                null,              50.26

Вариант 5. Варианты 3 и 4 используют таблицу, относящуюся к одной концепции (Клиент). Наши клиенты также запрашивают пользовательские поля в других формах. Должна ли мы вместо этого иметь общесистемную систему хранения пользовательских полей? Поэтому вместо того, чтобы иметь несколько таблиц, таких как CustomerCustomFieldValue, EmployeeCustomFieldValue, InvoiceCustomFieldValue, у нас была бы одна таблица с именем CustomFieldValue? Хотя для меня это кажется более изящным, не может ли это вызвать узкое место в производительности?

Вы использовали какой-либо из этих подходов? Вы были успешны? Какой подход вы бы выбрали? Знаете ли вы какой-либо другой подход, который я должен рассмотреть?

Кроме того, мои клиенты хотят, чтобы пользовательское поле могло ссылаться на данные в других таблицах. Например, клиент может захотеть добавить к "Клиенту" поле "Любимый способ оплаты". Способы оплаты определяются в других местах системы. Это приводит к теме "внешних ключей" на картинке. Должен ли я попытаться создать ограничения, чтобы гарантировать, что значения, хранящиеся в пользовательских таблицах полей, являются допустимыми значениями?

Спасибо

======================

EDIT 07-27-2009:

Спасибо за ваши ответы. Похоже, что список подходов теперь довольно всеобъемлющий. Я выбрал вариант 2 (один столбец XML). На данный момент это было проще всего реализовать. Мне, вероятно, придется преувеличивать более строго определенный подход, так как мои требования будут более сложными, а количество поддерживаемых настраиваемых полей будет больше.

4b9b3361

Ответ 1

Я согласен с плакатами ниже, что варианты 3, 4 или 5, скорее всего, будут уместны. Однако каждая из предлагаемых вами реализаций имеет свои преимущества и затраты. Я бы предложил выбрать один, сопоставив его с вашими конкретными требованиями. Например:

  • Вариант 1: Быстрый для реализации. Позволяет выполнять действия DB на настраиваемых полях (поиск, сортировка.)
    Вариант 1 минус: пользовательские поля являются общими, поэтому нет строго типизированных полей. Таблица базы данных неэффективна, по размеру со многими посторонними полями, которые никогда не будут использоваться. Необходимо указать количество настраиваемых полей.
  • Вариант 2: Быстро реализовать. Гибкость, позволяющая произвольное количество и тип настраиваемых полей.
    Вариант 2 минус: Никакие действия DB не возможны в настраиваемых полях. Это лучше всего, если все, что вам нужно сделать, это отобразить пользовательские поля, позже или сделать небольшие манипуляции с данными только на основе каждого клиента.
  • Преимущества 3-го варианта: гибкие и эффективные. Действия DB могут быть выполнены, но данные нормализуются несколько, чтобы уменьшить потраченное впустую пространство. Я согласен с неизвестным (google) предложением добавить дополнительный столбец, который можно использовать для указания типа или исходной информации. Вариант 3 минус: Небольшое увеличение времени разработки и сложности ваших запросов, но здесь действительно не так много минусов.
  • Вариант 4 совпадает с вариантом 3, за исключением того, что ваши типизированные данные могут работать на уровне БД. Добавление информации о типе в таблицу ссылок в Варианте 3 позволяет выполнять больше операций на уровне нашего приложения, но БД не сможет выполнять сравнения или сортировать, например. Выбор между 3 и 4 зависит от этого требования.
  • Вариант 5 такой же, как 3 или 4, но с еще большей гибкостью для применения решения для многих разных таблиц. Стоимость в этом случае будет заключаться в том, что размер этой таблицы будет намного больше. Если вы выполняете много дорогостоящих операций соединения, чтобы перейти к своим настраиваемым полям, это решение может плохо масштабироваться.

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

Ответ 2

Что касается кода приложения, я не уверен. Я знаю, что пользовательские поля в значительной степени выигрывают от

Ответ 3

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

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

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

Построение хорошего AOM с рабочим хранилищем данных для него - большая работа, и я бы не рекомендовал его, если у вас нет высококвалифицированных разработчиков. Возможно, когда-нибудь будет решение ОС для этих требований.

Пользовательские поля обсуждались ранее в SO:

Ответ 4

Что-то вроде варианта 3 - это путь, и я использовал этот метод ранее. Создайте единую таблицу для определения дополнительных свойств и их соответствующих значений. Это будет 1-N взаимосвязь между вашим клиентом и таблицей CustomerCustomField (соответственно). Второй вопрос, связанный с определением отношений с пользовательскими свойствами, - это то, о чем нужно подумать. Первое, что приходит на ум - это добавить поле DataSource, которое будет содержать таблицу, к которой привязано значение свойства. Таким образом, ваш CustomerCustomField будет выглядеть так:

  • CustomerId
  • Свойство
  • Значение
  • ValueDataSource (с нулевым значением)

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

Ответ 5

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

Некоторые мысли:

  • Убедитесь, что ваш CustomFields имеет столбец DataType.
    • Используйте ограничение проверки на основе UDF на CustomFieldValues, чтобы убедиться, что столбец, указанный CustomFields.DataType, не равен нулю.
    • Вам также потребуется стандартное ограничение проверки, чтобы убедиться, что у вас есть только одно ненулевое значение.
  • Что касается внешних ключей, я бы смоделировал их как отдельный DataType.
    • Каждая потенциальная ссылка для перекрестных таблиц потребует наличия собственного столбца. Это хорошо, потому что он поддерживает ссылочную целостность.
    • В любом случае вам придется поддерживать эти отношения в коде приложения, поэтому факт, что они жестко закодированы в базе данных, фактически не ограничивает функциональность.
    • Это также хорошо справится с вашим ORM, если вы его используете.
  • Для варианта 5 используйте промежуточные таблицы для моделирования отношений.
    • У вас все равно будет CustomerCustomFieldValue, но вместо этого только столбцы CustomerID и CustomFieldValueID.
  • Подумайте, долго и упорно о ваших ограничений каждый шаг пути. Это сложный материал, и одна ошибка может привести к полному хауку по линии.

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

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

Ответ 6

если эти дополнительные поля являются случайными и не хотят выполнять поиск на них, я обычно выбираю вариант 2 (но, как JSON, лучше, чем XML). Если в пользовательских полях будут выполняться поиски, опция 3 не сложна, и, как правило, оптимизатор SQL может получить разумную производительность.

Ответ 7

В настоящее время я работаю над проектом с этой же проблемой, и я решил использовать параметр 3, но я добавил поле FieldType и поле ListSource в случае FieldType = "list". Поле ListSource может быть запросом, представлением sql, именем функции или чем-то, что приводит к списку опций для списка. Самая большая проблема с попыткой хранения таких полей в моей ситуации заключается в том, что этот список полей может измениться, и пользователям разрешено редактировать данные позже. Итак, что делать, если список полей изменился, и они переходят к редактированию. Мое решение этого сценария состояло в том, чтобы разрешить редактирование только в том случае, если список не изменился и отобразить данные только для чтения, если он имеет.