Вопрос моделирования "один ко многим" - PullRequest
4 голосов
/ 11 марта 2009

Как лучше всего смоделировать следующее ...

Предположим, у меня есть два объекта: Agency и Publisher, и оба имеют отношение 1 к n к Employee. Это истинное отношение 1 к n, так как каждый Employee может работать только для одного Agency или одного Publisher. Давайте предположим, что я не могу представить супертип (например, Employer), который содержит отношение 1 к n.

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

Мой другой вариант - использовать две таблицы AgencyEmployee и PublisherEmployee, которые затем можно связать в виде традиционных двунаправленных ассоциаций 1-к-*.

Что вы считаете лучшей практикой в ​​этой ситуации?

ОБНОВЛЕНИЕ: Спасибо за отличные ответы в столь короткий промежуток времени! Что вы думаете о следующем решении: Внешние ключи в Employee для Agency и Publisher, такие как agency_id и publisher_id?

Ответы [ 6 ]

1 голос
/ 11 марта 2009

Лучшей практикой, вероятно, будет введение класса Employer.

Разделение сотрудника на AgencyEmployee и PublisherEmployee, с другой стороны, было бы плохим делом.

Если бы не было вопроса о представлении работодателя, я бы указал тип работодателя (Агентство или Издатель) в категории Сотрудник.

Ответ на обновленный вопрос:

Это вариант, но Employer_type лучше, потому что:

  1. Возможно, вы захотите добавить другие типы работодателей в будущем
  2. В каждой строке таблицы «Сотрудники» будет пустое поле.
0 голосов
/ 11 марта 2009

A +1 для Кан Берк Гудер.

Технически, введение супертипа Employer означает, что вы вводите отношение Employer со всеми атрибутами, общими для агентства и издателя, специфическое для Агентства (не знаю, как его называть) отношение с ключом Employer и всеми атрибутами, специфичными для агентства, и ключ Employer в качестве внешнего ключа, затем Агентство как запрос или представление, которое просто объединяет Специфическое Агентство с Работодателем, а также для Издателя.

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

Кстати, троичные отношения и даже отношения n-to-n не являются хорошей практикой проектирования, если вы спросите меня. Использование только функций (то есть 1-к-1 и 1-к-1), например ограничения становятся намного легче формулировать.

0 голосов
/ 11 марта 2009

Ясно, что сущность работодателя предпочтительнее, но в противном случае ...

Наличие таблиц AgencyEmployee & PublisherEmployee означает, что будет трудно определить, принадлежит ли сотрудник той или иной категории.

Поэтому вместо этого я бы добавил столбец EmployerType в таблицу Employees; это добавляет немного дополнительной сложности к вашим последующим запросам SQL, но работает в соответствии с заданными вами ограничениями.

Из интереса, почему вы могли бы добавлять таблицы AgencyEmployee & PublisherEmployee, но не добавлять таблицу Employer? Просто любопытно ...

0 голосов
/ 11 марта 2009

Я использовал этот подход:

Employee.EmployerType («АГЕНТСТВО» или «ИЗДАТЕЛЬ»)

Employee.EmployerID (AgencyID или PublisherID)

Это работает нормально, но вам нужна инструкция case во многих ваших SQL. Также вы, если используете ORM, теряете отношения с FK.

Я перемещаю большую часть своего кода в отношения n: m, чтобы я мог воспользоваться нашей поддержкой ORM FK.

0 голосов
/ 11 марта 2009

Я бы предпочел, чтобы таблица, которую вы явно не могли использовать (Супертип агентства и издателя; Работодатель)

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

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

Table1: Agency              (id, name, etc)
Table2: Publisher           (id, name, etc)
Table3: Employee            (id, name, etc)
Table4: AgencyEmployees     (agency_id, employee_id)
Table5: PublisherEmployees  (publisher_id, employee_id)


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

Table1: Agency              (id, name, etc)
Table2: Publisher           (id, name, etc)
Table3: Employee            (id, name, etc)
Table4: AgencyEmployees     (agency_id,    employee_id, start_date, leave_date)
Table5: PublisherEmployees  (publisher_id, employee_id, start_date, leave_date)

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

0 голосов
/ 11 марта 2009

Похоже, это можно смоделировать как троичное отношение . Посмотрите, нравится ли вам подход, использованный в этой статье MSDN.

...