Нужна помощь с дизайном приложения - PullRequest
3 голосов
/ 30 декабря 2010

Итак, я хотел бы получить отзывы о том, как лучше всего спроектировать классы и сохранить данные для следующей ситуации:

У меня есть интерфейс под названием Задачи, который выглядит следующим образом:

interface ITask
{
    int ID{ get; set;}
    string Title {get; set;}
    string Description{get; set;}
}

Мне бы хотелось иметь возможность создавать различные типы задач в зависимости от того, кто использует приложение ... например:

public class SoftwareTask: ITask
{
    //ITask Implementation
    string BuildVersion {get; set;}
    bool IsBug {get; set;}

}

public class SalesTask: ITask
{
    //ITask Implementation
    int AccountID {get; set;}
    int SalesPersonID {get; set;}
}

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

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

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

Любая помощь или толчок в правильном направлении очень ценится !!!

Ответы [ 2 ]

3 голосов
/ 30 декабря 2010

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

Однако существует несколько альтернативных подходов, иногда используемых, когда числоподтипов очень велико, или подтипы создаются на лету.

Альтернатива # 1: Таблица расширений Key-Value. Это таблица с одной строкой на дополнительное поледанных, которые вы хотите сохранить, внешний ключ обратно в основную таблицу (Task) и столбец, в котором указано, что это за поле.Его структура, как правило, выглядит примерно так:

TaskExt Table
=================
TaskID     : Number (foreign key back to Task)
FieldType  : Number or String (this would be AccountID, SalesPersonID, etc)
FieldValue : String  (this would be the value of the associated field)

Альтернатива # 2: Таблица расширений с отображением типа. В этом варианте вы создаете таблицу с кучей обнуляемых столбцов различных данных.типы (числа, строки, дата / время и т. д.) с такими именами, как DATA01, DATA02, DATA03 ... и т. д.Для каждого типа задач вы выбираете подмножество столбцов и сопоставляете их с определенными полями.Таким образом, DATA01 может оказаться BuildVersion для SoftwareTask и AccountName для SalesTask.При таком подходе вы должны где-то управлять метаданными, которые управляют тем, к какому столбцу вы привязываете определенные поля.Таблица отображения типов часто выглядит примерно так:

TaskExt Table
=================
TaskID   : Number  (foreign key back to task)
Data01   : String
Data02   : String
Data03   : String
Data04   : String
Data05   : Number
Data06   : Number
Data07   : Number
Data08   : Number
Data09   : Date
Data10   : Date
Data11   : Date
Data12   : Date
// etc...

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

Преимущества варианта №2 заключаются в простоте реализации и сохранении соответствия между строками в соотношении 1: 1, что упрощает запросы.,К сожалению, в этом есть и недостатки.Во-первых, имена столбцов полностью неинформативны, и вам необходимо обратиться к некоторому словарю метаданных, чтобы понять, какие столбцы соответствуют какому полю для какого типа задачи.Вторым недостатком является то, что большинство баз данных ограничивают количество столбцов в таблице относительно небольшим числом (обычно 50–300 столбцов).В результате вы можете использовать только столько числовых, строковых столбцов, столбцов даты и времени, доступных для использования.Таким образом, если при вводе текста у вас будет больше полей DateTime, чем поддерживает таблица, вам придется либо использовать строковые поля для хранения дат, либо создать несколько таблиц расширений.

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

3 голосов
/ 30 декабря 2010

Вы, вероятно, должны руководствоваться тем, как ORM справляются с этим, например TPH / TPC / TPT

Учитывая, что ITask является интерфейсом, вы, вероятно, должны использовать TPC (таблица для конкретного типа). Когда вы делаете его базовым классом, TPT и TPH также являются опциями.

...